]> git.ipfire.org Git - thirdparty/pdns.git/commitdiff
dnsdist: Better handling of reconnection failures
authorRemi Gacogne <remi.gacogne@powerdns.com>
Mon, 5 Oct 2020 12:39:08 +0000 (14:39 +0200)
committerRemi Gacogne <remi.gacogne@powerdns.com>
Tue, 10 Nov 2020 08:52:24 +0000 (09:52 +0100)
pdns/dnsdist-tcp.cc
pdns/dnsdistdist/dnsdist-tcp-downstream.cc

index 1f5387e274ed19c928a1a4b1c6a1f21deac05608..db1747410154857f18f96deaac2429a3360e06b0 100644 (file)
@@ -935,6 +935,13 @@ static void tcpClientThread(int pipefd)
     if (g_downstreamTCPCleanupInterval > 0 && (now.tv_sec > (lastTCPCleanup + g_downstreamTCPCleanupInterval))) {
       DownstreamConnectionsManager::cleanupClosedTCPConnections();
       lastTCPCleanup = now.tv_sec;
+
+      /*
+      data.mplexer->runForAllWatchedFDs([](bool isRead, int fd, const FDMultiplexer::funcparam_t& param, struct timeval ttd)
+      {
+        cerr<<"- "<<isRead<<" "<<fd<<": "<<param.type().name()<<" "<<ttd.tv_sec<<endl;
+      });
+      */
     }
 
     if (now.tv_sec > lastTimeoutScan) {
index 8e63caf70e47114cb045dc3558a6916b89fccda8..622b6a93316e0daf8e56569469c08d67bac81a0c 100644 (file)
@@ -213,38 +213,44 @@ void TCPConnectionToBackend::handleIO(std::shared_ptr<TCPConnectionToBackend>& c
       conn->d_ioState->reset();
       ioGuard.release();
 
-      if (conn->reconnect()) {
-        conn->d_ioState = make_unique<IOStateHandler>(conn->d_clientConn->getIOMPlexer(), conn->d_socket->getHandle());
-
-        /* we need to resend the queries that were in flight, if any */
-        for (auto& pending : conn->d_pendingResponses) {
-          conn->d_pendingQueries.push_back(std::move(pending.second));
-          if (!conn->d_usedForXFR) {
-            --conn->d_ds->outstanding;
+      try {
+        if (conn->reconnect()) {
+          conn->d_ioState = make_unique<IOStateHandler>(conn->d_clientConn->getIOMPlexer(), conn->d_socket->getHandle());
+
+          /* we need to resend the queries that were in flight, if any */
+          for (auto& pending : conn->d_pendingResponses) {
+            conn->d_pendingQueries.push_back(std::move(pending.second));
+            if (!conn->d_usedForXFR) {
+              --conn->d_ds->outstanding;
+            }
           }
-        }
-        conn->d_pendingResponses.clear();
-        conn->d_currentPos = 0;
+          conn->d_pendingResponses.clear();
+          conn->d_currentPos = 0;
 
-        if (conn->d_state == State::doingHandshake ||
-            conn->d_state == State::sendingQueryToBackend) {
-          iostate = IOState::NeedWrite;
-          // resume sending query
-        }
-        else {
-          if (conn->d_pendingQueries.empty()) {
-            throw std::runtime_error("TCP connection to a backend in state " + std::to_string((int)conn->d_state) + " with no pending queries");
+          if (conn->d_state == State::doingHandshake ||
+              conn->d_state == State::sendingQueryToBackend) {
+            iostate = IOState::NeedWrite;
+            // resume sending query
           }
+          else {
+            if (conn->d_pendingQueries.empty()) {
+              throw std::runtime_error("TCP connection to a backend in state " + std::to_string((int)conn->d_state) + " with no pending queries");
+            }
 
-          iostate = queueNextQuery(conn);
-        }
+            iostate = queueNextQuery(conn);
+          }
 
-        if (!conn->d_proxyProtocolPayloadAdded && !conn->d_proxyProtocolPayload.empty()) {
-          conn->d_currentQuery.d_buffer.insert(conn->d_currentQuery.d_buffer.begin(), conn->d_proxyProtocolPayload.begin(), conn->d_proxyProtocolPayload.end());
-          conn->d_proxyProtocolPayloadAdded = true;
-        }
+          if (!conn->d_proxyProtocolPayloadAdded && !conn->d_proxyProtocolPayload.empty()) {
+            conn->d_currentQuery.d_buffer.insert(conn->d_currentQuery.d_buffer.begin(), conn->d_proxyProtocolPayload.begin(), conn->d_proxyProtocolPayload.end());
+            conn->d_proxyProtocolPayloadAdded = true;
+          }
 
-        reconnected = true;
+          reconnected = true;
+        }
+      }
+      catch (const std::exception& e) {
+        // reconnect might throw on failure, let's ignore that, we just need to know
+        // it failed
       }
     }