From: Remi Gacogne Date: Wed, 16 Jan 2019 14:19:17 +0000 (+0100) Subject: rec: Try another worker before failing if the first pipe was full X-Git-Tag: rec-4.1.9~1^2 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=refs%2Fpull%2F7377%2Fhead;p=thirdparty%2Fpdns.git rec: Try another worker before failing if the first pipe was full --- diff --git a/pdns/pdns_recursor.cc b/pdns/pdns_recursor.cc index 9ca5461626..bc37565e81 100644 --- a/pdns/pdns_recursor.cc +++ b/pdns/pdns_recursor.cc @@ -2310,27 +2310,14 @@ void broadcastFunction(const pipefunc_t& func) } } -// This function is only called by the distributor thread, when pdns-distributes-queries is set -void distributeAsyncFunction(const string& packet, const pipefunc_t& func) +static bool trySendingQueryToWorker(unsigned int target, ThreadMSG* tmsg) { - if (t_id != s_distributorThreadID) { - L<(s_distributorThreadID)) { L<func = func; - tmsg->wantAnswer = false; - ssize_t written = write(tps.writeQueriesToThread, &tmsg, sizeof(tmsg)); if (written > 0) { if (static_cast(written) != sizeof(tmsg)) { @@ -2340,13 +2327,46 @@ void distributeAsyncFunction(const string& packet, const pipefunc_t& func) } else { int error = errno; - delete tmsg; if (error == EAGAIN || error == EWOULDBLOCK) { - g_stats.queryPipeFullDrops++; + /* the pipe is full, sorry */ + return false; } else { + delete tmsg; unixDie("write to thread pipe returned wrong size or error:" + std::to_string(error)); } } + + return true; +} + +// This function is only called by the distributor thread, when pdns-distributes-queries is set +void distributeAsyncFunction(const string& packet, const pipefunc_t& func) +{ + if (t_id != s_distributorThreadID) { + L<func = func; + tmsg->wantAnswer = false; + + if (!trySendingQueryToWorker(target, tmsg)) { + /* if this function failed but did not raise an exception, it means that the pipe + was full, let's try another one */ + unsigned int newTarget = 0; + do { + newTarget = 1 + dns_random(g_pipes.size()-1); + } while (newTarget == target); + + if (!trySendingQueryToWorker(newTarget, tmsg)) { + g_stats.queryPipeFullDrops++; + delete tmsg; + } + } } static void handlePipeRequest(int fd, FDMultiplexer::funcparam_t& var)