From: Remi Gacogne Date: Tue, 24 Jan 2023 10:05:17 +0000 (+0100) Subject: mplexer: Fix infinite (-1) timeout with kqueue and ports implementations X-Git-Tag: dnsdist-1.8.0-rc1~86^2~1 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=c0c6d1e72399e85d3848b32676287a3cd9c243da;p=thirdparty%2Fpdns.git mplexer: Fix infinite (-1) timeout with kqueue and ports implementations --- diff --git a/pdns/kqueuemplexer.cc b/pdns/kqueuemplexer.cc index 2c426a69c7..e843332601 100644 --- a/pdns/kqueuemplexer.cc +++ b/pdns/kqueuemplexer.cc @@ -145,7 +145,7 @@ void KqueueFDMultiplexer::getAvailableFDs(std::vector& fds, int timeout) ts.tv_sec = timeout / 1000; ts.tv_nsec = (timeout % 1000) * 1000000; - int ret = kevent(d_kqueuefd, 0, 0, d_kevents.data(), d_kevents.size(), &ts); + int ret = kevent(d_kqueuefd, 0, 0, d_kevents.data(), d_kevents.size(), timeout != -1 ? &ts : nullptr); if (ret < 0 && errno != EINTR) { throw FDMultiplexerException("kqueue returned error: " + stringerror()); @@ -174,7 +174,7 @@ int KqueueFDMultiplexer::run(struct timeval* now, int timeout) ts.tv_sec = timeout / 1000; ts.tv_nsec = (timeout % 1000) * 1000000; - int ret = kevent(d_kqueuefd, 0, 0, d_kevents.data(), d_kevents.size(), &ts); + int ret = kevent(d_kqueuefd, 0, 0, d_kevents.data(), d_kevents.size(), timeout != -1 ? &ts : nullptr); gettimeofday(now, nullptr); // MANDATORY! if (ret < 0 && errno != EINTR) { diff --git a/pdns/mplexer.hh b/pdns/mplexer.hh index bba581c31f..70b36d221f 100644 --- a/pdns/mplexer.hh +++ b/pdns/mplexer.hh @@ -83,7 +83,8 @@ public: static FDMultiplexer* getMultiplexerSilent(unsigned int maxEventsHint = s_maxevents); /* tv will be updated to 'now' before run returns */ - /* timeout is in ms */ + /* timeout is in ms, 0 will return immediately, -1 will block until at + least one descriptor is ready */ /* returns 0 on timeout, -1 in case of error (but all implementations actually throw in that case) and the number of ready events otherwise. Note that We might have two events (read AND write) for the same descriptor */ diff --git a/pdns/portsmplexer.cc b/pdns/portsmplexer.cc index 86605a363c..86bd563041 100644 --- a/pdns/portsmplexer.cc +++ b/pdns/portsmplexer.cc @@ -94,7 +94,7 @@ void PortsFDMultiplexer::getAvailableFDs(std::vector& fds, int timeout) timeoutspec.tv_sec = timeout / 1000; timeoutspec.tv_nsec = (timeout % 1000) * 1000000; unsigned int numevents = 1; - int ret = port_getn(d_portfd, d_pevents.data(), min(PORT_MAX_LIST, static_cast(d_pevents.size())), &numevents, &timeoutspec); + int ret = port_getn(d_portfd, d_pevents.data(), min(PORT_MAX_LIST, static_cast(d_pevents.size())), &numevents, timeout != -1 ? &timeoutspec : nullptr); /* port_getn has an unusual API - (ret == -1, errno == ETIME) can mean partial success; you must check (*numevents) in this case @@ -155,7 +155,7 @@ int PortsFDMultiplexer::run(struct timeval* now, int timeout) timeoutspec.tv_sec = timeout / 1000; timeoutspec.tv_nsec = (timeout % 1000) * 1000000; unsigned int numevents = 1; - int ret = port_getn(d_portfd, d_pevents.data(), min(PORT_MAX_LIST, static_cast(d_pevents.size())), &numevents, &timeoutspec); + int ret = port_getn(d_portfd, d_pevents.data(), min(PORT_MAX_LIST, static_cast(d_pevents.size())), &numevents, timeout != -1 ? &timeoutspec : nullptr); /* port_getn has an unusual API - (ret == -1, errno == ETIME) can mean partial success; you must check (*numevents) in this case diff --git a/pdns/test-mplexer.cc b/pdns/test-mplexer.cc index 327eb39d22..5a6bbde62b 100644 --- a/pdns/test-mplexer.cc +++ b/pdns/test-mplexer.cc @@ -72,7 +72,8 @@ BOOST_AUTO_TEST_CASE(test_MPlexer) BOOST_REQUIRE_EQUAL(readyFDs.size(), 1U); BOOST_CHECK_EQUAL(readyFDs.at(0), pipes[1]); - ready = mplexer->run(&now, 100); + /* wait until we have at least one descriptor ready */ + ready = mplexer->run(&now, -1); BOOST_CHECK_EQUAL(ready, 1); BOOST_CHECK_EQUAL(writeCBCalled, true);