]> git.ipfire.org Git - thirdparty/pdns.git/commitdiff
dnsdist: Fix the oustanding counter when an exception is raised
authorRemi Gacogne <remi.gacogne@powerdns.com>
Thu, 14 Dec 2017 11:28:34 +0000 (12:28 +0100)
committerRemi Gacogne <remi.gacogne@powerdns.com>
Thu, 14 Dec 2017 11:28:34 +0000 (12:28 +0100)
If an exception is raised in the responder thread after the outstanding
queries counter has been decremented, but before we could mark the
state as processed, the same state would be processed again and the
counter decremented a second time, either because of a duplicate
answer or more likely by the timeout handler.
This commit simply increase back the outstanding counter when such
an exception occurs.

pdns/dnsdist.cc

index 9fbf6703c119a8f9b002dffaba0218448d67cd1e..f211835452979f2a18276f62ec20864565ac401e 100644 (file)
@@ -404,6 +404,7 @@ try {
   uint16_t queryId = 0;
   for(;;) {
     dnsheader* dh = reinterpret_cast<struct dnsheader*>(packet);
+    bool outstandingDecreased = false;
     try {
       ssize_t got = recv(state->fd, packet, sizeof(packet), 0);
       char * response = packet;
@@ -436,6 +437,7 @@ try {
       }
 
       --state->outstanding;  // you'd think an attacker could game this, but we're using connected socket
+      outstandingDecreased = true;
 
       if(dh->tc && g_truncateTC) {
         truncateTC(response, &responseLen);
@@ -509,12 +511,21 @@ try {
         ids->dnsCryptQuery = nullptr;
 #endif
         ids->origFD = -1;
+        outstandingDecreased = false;
       }
 
       rewrittenResponse.clear();
     }
-    catch(std::exception& e){
+    catch(const std::exception& e){
       vinfolog("Got an error in UDP responder thread while parsing a response from %s, id %d: %s", state->remote.toStringWithPort(), queryId, e.what());
+      if (outstandingDecreased) {
+        /* so an exception was raised after we decreased the outstanding queries counter,
+           but before we could set ids->origFD to -1 (because we also set outstandingDecreased
+           to false then), meaning the IDS still considered active and we will decrease the
+           counter again on a duplicate, or simply while reaping downstream timeouts, so let's
+           increase it back. */
+        state->outstanding++;
+      }
     }
   }
   return 0;