From: Remi Gacogne Date: Mon, 10 Jul 2023 15:49:51 +0000 (+0200) Subject: dnsdist: Better handling of spurious wake-ups, interrupted calls X-Git-Tag: rec-5.0.0-alpha1~97^2~4 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=b92f183afd503cb683427845c2b91bb52a3d12a4;p=thirdparty%2Fpdns.git dnsdist: Better handling of spurious wake-ups, interrupted calls If we were woken up by the multiplexer but have actually nothing to read, or the call to `recv()` is interrupted, we do not want to stop listening for the health-check response event. It is also not useful to log about it, even at "verbose health-check" level. Note that we would have logged previously, so this kind of event would not have gone unnoticed anyway. --- diff --git a/pdns/dnsdistdist/dnsdist-healthchecks.cc b/pdns/dnsdistdist/dnsdist-healthchecks.cc index 4df42302f3..e04ef5a56e 100644 --- a/pdns/dnsdistdist/dnsdist-healthchecks.cc +++ b/pdns/dnsdistdist/dnsdist-healthchecks.cc @@ -169,22 +169,37 @@ private: static void healthCheckUDPCallback(int fd, FDMultiplexer::funcparam_t& param) { auto data = boost::any_cast>(param); - data->d_mplexer.removeReadFD(fd); + ssize_t got = 0; ComboAddress from; - from.sin4.sin_family = data->d_ds->d_config.remote.sin4.sin_family; - auto fromlen = from.getSocklen(); - data->d_buffer.resize(512); - auto got = recvfrom(data->d_udpSocket.getHandle(), &data->d_buffer.at(0), data->d_buffer.size(), 0, reinterpret_cast(&from), &fromlen); - if (got < 0) { - int savederrno = errno; - if (g_verboseHealthChecks) { - infolog("Error receiving health check response from %s: %s", data->d_ds->d_config.remote.toStringWithPort(), stringerror(savederrno)); + do { + from.sin4.sin_family = data->d_ds->d_config.remote.sin4.sin_family; + auto fromlen = from.getSocklen(); + data->d_buffer.resize(512); + + got = recvfrom(data->d_udpSocket.getHandle(), &data->d_buffer.at(0), data->d_buffer.size(), 0, reinterpret_cast(&from), &fromlen); + if (got < 0) { + int savederrno = errno; + if (savederrno == EINTR) { + /* interrupted, let's try again */ + continue; + } + if (savederrno == EWOULDBLOCK || savederrno == EAGAIN) { + /* spurious wake-up, let's return to sleep */ + return; + } + + if (g_verboseHealthChecks) { + infolog("Error receiving health check response from %s: %s", data->d_ds->d_config.remote.toStringWithPort(), stringerror(savederrno)); + } + ++data->d_ds->d_healthCheckMetrics.d_networkErrors; + data->d_ds->submitHealthCheckResult(data->d_initial, false); + data->d_mplexer.removeReadFD(fd); + return; } - ++data->d_ds->d_healthCheckMetrics.d_networkErrors; - data->d_ds->submitHealthCheckResult(data->d_initial, false); - return; } + while (got < 0); + data->d_buffer.resize(static_cast(got)); /* we are using a connected socket but hey.. */ @@ -197,6 +212,7 @@ static void healthCheckUDPCallback(int fd, FDMultiplexer::funcparam_t& param) return; } + data->d_mplexer.removeReadFD(fd); data->d_ds->submitHealthCheckResult(data->d_initial, handleResponse(data)); }