]> git.ipfire.org Git - thirdparty/pdns.git/commitdiff
auth: Wait for the connection to the carbon server to be established 4126/head
authorRemi Gacogne <remi.gacogne@powerdns.com>
Wed, 6 Jul 2016 16:12:08 +0000 (18:12 +0200)
committerRemi Gacogne <remi.gacogne@powerdns.com>
Wed, 6 Jul 2016 16:12:08 +0000 (18:12 +0200)
Doing a non-blocking `connect()` immediately followed by a `write()`
cause the `write()` to fail with `ENOTCONN` on FreeBSD.
This commit instead wait for the `connect()` operation to finish
using `poll()` with a short timeout if it returned `EINPROGRESS`,
so that either we have a connected socket to write to, or we fail.

pdns/auth-carbon.cc
pdns/sstuff.hh

index c721cc0155e63aecdbe3f37fd82cfc7f81aa4360..17a43b365d6802a78fd562eb02b96b5b4ba67a7a 100644 (file)
@@ -46,11 +46,12 @@ try
 
     for (const auto& carbonServer : carbonServers) {
       ComboAddress remote(carbonServer, 2003);
-      Socket s(remote.sin4.sin_family, SOCK_STREAM);
-      s.setNonBlocking();
-      s.connect(remote);  // we do the connect so the attempt happens while we gather stats
 
       try {
+        Socket s(remote.sin4.sin_family, SOCK_STREAM);
+        s.setNonBlocking();
+        s.connect(remote, 2);
+
         writen2WithTimeout(s.getHandle(), msg.c_str(), msg.length(), 2);
       } catch (runtime_error &e){
         L<<Logger::Warning<<"Unable to write data to carbon server at "<<remote.toStringWithPort()<<": "<<e.what()<<endl;
index 274577c92ea1bfe43d1a447090e7119f508f551c..a586ec30dcb270dc747b7e1dd49def10621d33be 100644 (file)
@@ -137,10 +137,24 @@ public:
   }
 #endif
   //! Connect the socket to a specified endpoint
-  void connect(const ComboAddress &ep)
+  void connect(const ComboAddress &ep, int timeout=0)
   {
-    if(::connect(d_socket,(struct sockaddr *)&ep, ep.getSocklen()) < 0 && errno != EINPROGRESS)
-      throw NetworkError("While connecting to "+ep.toStringWithPort()+": "+string(strerror(errno)));
+    if(::connect(d_socket,(struct sockaddr *)&ep, ep.getSocklen()) < 0) {
+      if(errno == EINPROGRESS) {
+        if (timeout > 0) {
+          /* if a timeout is provided, we wait until the connection has been established */
+          int res = waitForRWData(d_socket, false, timeout, 0);
+          if (res == 0) {
+            throw NetworkError("timeout while connecting to "+ep.toStringWithPort());
+          } else if (res < 0) {
+            throw NetworkError("while waiting to connect to "+ep.toStringWithPort()+": "+string(strerror(errno)));
+          }
+        }
+      }
+      else {
+        throw NetworkError("While connecting to "+ep.toStringWithPort()+": "+string(strerror(errno)));
+      }
+    }
   }