From: Otto Date: Mon, 8 Nov 2021 12:32:50 +0000 (+0100) Subject: Use a global timeout for the various recv's we're doing to get a control message X-Git-Tag: rec-4.6.0-beta1^2~2 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=5fc89ddc7a74d3b88abcbe324fb85f45bc03d34d;p=thirdparty%2Fpdns.git Use a global timeout for the various recv's we're doing to get a control message --- diff --git a/pdns/rec_channel.cc b/pdns/rec_channel.cc index b288abe832..41faffddb6 100644 --- a/pdns/rec_channel.cc +++ b/pdns/rec_channel.cc @@ -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) {