]> git.ipfire.org Git - thirdparty/pdns.git/commitdiff
mplexer: Fix infinite (-1) timeout with kqueue and ports implementations
authorRemi Gacogne <remi.gacogne@powerdns.com>
Tue, 24 Jan 2023 10:05:17 +0000 (11:05 +0100)
committerRemi Gacogne <remi.gacogne@powerdns.com>
Tue, 24 Jan 2023 10:05:17 +0000 (11:05 +0100)
pdns/kqueuemplexer.cc
pdns/mplexer.hh
pdns/portsmplexer.cc
pdns/test-mplexer.cc

index 2c426a69c7606d8b7366383d3c14f19cac32b8cf..e843332601f2a74cfb4644125bf93aa5990ea6c9 100644 (file)
@@ -145,7 +145,7 @@ void KqueueFDMultiplexer::getAvailableFDs(std::vector<int>& 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) {
index bba581c31f8d5835a6e8a102570a3771b3d75a71..70b36d221f67476c23bc456a7d81c167e4e5814d 100644 (file)
@@ -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 */
index 86605a363c49201d384b629360118c757efa1e46..86bd56304177e5cf4894ee70957602de752111dc 100644 (file)
@@ -94,7 +94,7 @@ void PortsFDMultiplexer::getAvailableFDs(std::vector<int>& 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<int>(d_pevents.size())), &numevents, &timeoutspec);
+  int ret = port_getn(d_portfd, d_pevents.data(), min(PORT_MAX_LIST, static_cast<int>(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<int>(d_pevents.size())), &numevents, &timeoutspec);
+  int ret = port_getn(d_portfd, d_pevents.data(), min(PORT_MAX_LIST, static_cast<int>(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
index 327eb39d22608701f880373706f10d33df22e60c..5a6bbde62b1d5b72015667dca4d4e821c79686bc 100644 (file)
@@ -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);