]> git.ipfire.org Git - thirdparty/pdns.git/commitdiff
dnsdist: Fix handling of backend connection failing over TCP 7979/head
authorRemi Gacogne <remi.gacogne@powerdns.com>
Tue, 25 Jun 2019 08:42:59 +0000 (10:42 +0200)
committerRemi Gacogne <remi.gacogne@powerdns.com>
Tue, 25 Jun 2019 08:42:59 +0000 (10:42 +0200)
- The creation of the Socket object can throw if we run out of file
descriptors ;
- Catch exceptions thrown from setupTCPDownstream() earlier, we don't
care why it failed later, only that it did.

pdns/dnsdist-tcp.cc

index 8419011661fd5022e8df2547b6c7d906652bcb72..405a9125d5cd2414bbef55dd186973d909e07d5f 100644 (file)
@@ -71,8 +71,8 @@ static std::unique_ptr<Socket> setupTCPDownstream(shared_ptr<DownstreamState>& d
 
   do {
     vinfolog("TCP connecting to downstream %s (%d)", ds->remote.toStringWithPort(), downstreamFailures);
-    result = std::unique_ptr<Socket>(new Socket(ds->remote.sin4.sin_family, SOCK_STREAM, 0));
     try {
+      result = std::unique_ptr<Socket>(new Socket(ds->remote.sin4.sin_family, SOCK_STREAM, 0));
       if (!IsAnyAddress(ds->sourceAddr)) {
         SSetsockopt(result->getHandle(), SOL_SOCKET, SO_REUSEADDR, 1);
 #ifdef IP_BIND_ADDRESS_NO_PORT
@@ -750,24 +750,24 @@ static void sendQueryToBackend(std::shared_ptr<IncomingTCPConnectionState>& stat
     return;
   }
 
-  while (state->d_downstreamFailures < state->d_ds->retries)
-  {
-    state->d_downstreamConnection = getConnectionToDownstream(ds, state->d_downstreamFailures, now);
-
-    if (!state->d_downstreamConnection) {
-      ++ds->tcpGaveUp;
-      ++state->d_ci.cs->tcpGaveUp;
-      vinfolog("Downstream connection to %s failed %d times in a row, giving up.", ds->getName(), state->d_downstreamFailures);
-      return;
+  if (state->d_downstreamFailures < state->d_ds->retries) {
+    try {
+      state->d_downstreamConnection = getConnectionToDownstream(ds, state->d_downstreamFailures, now);
     }
+    catch (const std::runtime_error& e) {
+      state->d_downstreamConnection.reset();
+    }
+  }
 
-    handleDownstreamIO(state, now);
+  if (!state->d_downstreamConnection) {
+    ++ds->tcpGaveUp;
+    ++state->d_ci.cs->tcpGaveUp;
+    vinfolog("Downstream connection to %s failed %d times in a row, giving up.", ds->getName(), state->d_downstreamFailures);
     return;
   }
 
-  ++ds->tcpGaveUp;
-  ++state->d_ci.cs->tcpGaveUp;
-  vinfolog("Downstream connection to %s failed %u times in a row, giving up.", ds->getName(), state->d_downstreamFailures);
+  handleDownstreamIO(state, now);
+  return;
 }
 
 static void handleQuery(std::shared_ptr<IncomingTCPConnectionState>& state, struct timeval& now)