]> git.ipfire.org Git - thirdparty/pdns.git/commitdiff
Use a global timeout for the various recv's we're doing to get a control message
authorOtto <otto.moerbeek@open-xchange.com>
Mon, 8 Nov 2021 12:32:50 +0000 (13:32 +0100)
committerOtto <otto.moerbeek@open-xchange.com>
Mon, 8 Nov 2021 12:32:50 +0000 (13:32 +0100)
pdns/rec_channel.cc

index b288abe8325970e955ed241f073ff4fe0c667aaf..41faffddb649d181724f19fe7d390f26a88f9810 100644 (file)
@@ -152,16 +152,30 @@ void RecursorControlChannel::send(int fd, const Answer& msg, unsigned int timeou
   }
 }
 
-RecursorControlChannel::Answer RecursorControlChannel::recv(int fd, unsigned int timeout)
+static void waitForRead(int fd, unsigned int timeout, time_t start)
 {
-  int ret = waitForData(fd, timeout, 0);
+  time_t elapsed = time(nullptr) - start;
+  if (elapsed >= timeout) {
+    throw PDNSException("Timeout waiting for control channel data");
+  }
+  int ret = waitForData(fd, timeout - elapsed, 0);
   if (ret == 0) {
-    throw PDNSException("Timeout waiting for answer from control channel");
+    throw PDNSException("Timeout waiting for control channel data");
   }
+}
+
+RecursorControlChannel::Answer RecursorControlChannel::recv(int fd, unsigned int timeout)
+{
+  // timeout covers the operation of all read ops combined
+  const time_t start = time(nullptr);
+
+  waitForRead(fd, timeout, start);
   int err;
   if (::recv(fd, &err, sizeof(err), 0) != sizeof(err)) {
     throw PDNSException("Unable to receive return status over control channel: " + stringerror());
   }
+
+  waitForRead(fd, timeout, start);
   size_t len;
   if (::recv(fd, &len, sizeof(len), 0) != sizeof(len)) {
     throw PDNSException("Unable to receive length over control channel: " + stringerror());
@@ -171,6 +185,7 @@ RecursorControlChannel::Answer RecursorControlChannel::recv(int fd, unsigned int
   str.reserve(len);
   while (str.length() < len) {
     char buffer[1024];
+    waitForRead(fd, timeout, start);
     size_t toRead = std::min(len - str.length(), sizeof(buffer));
     ssize_t recvd = ::recv(fd, buffer, toRead, 0);
     if (recvd <= 0) {