]> git.ipfire.org Git - thirdparty/pdns.git/blobdiff - pdns/devpollmplexer.cc
mplexer: Make it possible to set the read TTD right away
[thirdparty/pdns.git] / pdns / devpollmplexer.cc
index 53c39f30d48aa3f451f81515d308a87f9c64455a..8b5d531f16909ab1dbd2812d118f9540fef78569 100644 (file)
@@ -1,16 +1,40 @@
+/*
+ * This file is part of PowerDNS or dnsdist.
+ * Copyright -- PowerDNS.COM B.V. and its contributors
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of version 2 of the GNU General Public License as
+ * published by the Free Software Foundation.
+ *
+ * In addition, for the avoidance of any doubt, permission is granted to
+ * link this program with OpenSSL and to (re)distribute the binaries
+ * produced as the result of such linking.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
 #ifdef HAVE_CONFIG_H
 #include "config.h"
 #endif
+/*
+ * NOTE: sys/devpoll.h relies on sigset_t being already defined so we need
+ * to include sys/signal.h *before* including sys/devpoll.h.
+ */
+#include <sys/signal.h>
 #include <sys/devpoll.h>
 #include "mplexer.hh"
 #include "sstuff.hh"
 #include <iostream>
 #include <unistd.h>
 #include "misc.hh"
-#include <boost/lexical_cast.hpp>
 #include "syncres.hh"
 
-#include "namespaces.hh"
 #include "namespaces.hh"
 
 class DevPollFDMultiplexer : public FDMultiplexer
@@ -22,11 +46,12 @@ public:
     close(d_devpollfd);
   }
 
-  virtual int run(struct timeval* tv);
+  virtual int run(struct timeval* tv, int timeout=500) override;
+  virtual void getAvailableFDs(std::vector<int>& fds, int timeout) override;
 
-  virtual void addFD(callbackmap_t& cbmap, int fd, callbackfunc_t toDo, const funcparam_t& parameter);
-  virtual void removeFD(callbackmap_t& cbmap, int fd);
-  string getName()
+  virtual void addFD(callbackmap_t& cbmap, int fd, callbackfunc_t toDo, const funcparam_t& parameter, const struct timeval* ttd=nullptr) override;
+  virtual void removeFD(callbackmap_t& cbmap, int fd) override;
+  string getName() const override
   {
     return "/dev/poll";
   }
@@ -57,9 +82,9 @@ DevPollFDMultiplexer::DevPollFDMultiplexer()
     
 }
 
-void DevPollFDMultiplexer::addFD(callbackmap_t& cbmap, int fd, callbackfunc_t toDo, const funcparam_t& parameter)
+void DevPollFDMultiplexer::addFD(callbackmap_t& cbmap, int fd, callbackfunc_t toDo, const funcparam_t& parameter, const struct timeval* ttd)
 {
-  accountingAddFD(cbmap, fd, toDo, parameter);
+  accountingAddFD(cbmap, fd, toDo, parameter, ttd);
 
   struct pollfd devent;
   devent.fd=fd;
@@ -75,7 +100,7 @@ void DevPollFDMultiplexer::addFD(callbackmap_t& cbmap, int fd, callbackfunc_t to
 void DevPollFDMultiplexer::removeFD(callbackmap_t& cbmap, int fd)
 {
   if(!cbmap.erase(fd))
-    throw FDMultiplexerException("Tried to remove unlisted fd "+lexical_cast<string>(fd)+ " from multiplexer");
+    throw FDMultiplexerException("Tried to remove unlisted fd "+std::to_string(fd)+ " from multiplexer");
 
   struct pollfd devent;
   devent.fd=fd;
@@ -88,7 +113,27 @@ void DevPollFDMultiplexer::removeFD(callbackmap_t& cbmap, int fd)
   }
 }
 
-int DevPollFDMultiplexer::run(struct timeval* now)
+void DevPollFDMultiplexer::getAvailableFDs(std::vector<int>& fds, int timeout)
+{
+  struct dvpoll dvp;
+  dvp.dp_nfds = d_readCallbacks.size() + d_writeCallbacks.size();
+  dvp.dp_fds = new pollfd[dvp.dp_nfds];
+  dvp.dp_timeout = timeout;
+  int ret=ioctl(d_devpollfd, DP_POLL, &dvp);
+
+  if(ret < 0 && errno!=EINTR) {
+    delete[] dvp.dp_fds;
+    throw FDMultiplexerException("/dev/poll returned error: "+stringerror());
+  }
+
+  for(int n=0; n < ret; ++n) {
+    fds.push_back(dvp.dp_fds[n].fd);
+  }
+
+  delete[] dvp.dp_fds;
+}
+
+int DevPollFDMultiplexer::run(struct timeval* now, int timeout)
 {
   if(d_inrun) {
     throw FDMultiplexerException("FDMultiplexer::run() is not reentrant!\n");
@@ -96,15 +141,19 @@ int DevPollFDMultiplexer::run(struct timeval* now)
   struct dvpoll dvp;
   dvp.dp_nfds = d_readCallbacks.size() + d_writeCallbacks.size();
   dvp.dp_fds = new pollfd[dvp.dp_nfds];
-  dvp.dp_timeout = 500;
-  int ret=ioctl(d_devpollfd, DP_POLL, &dvp); 
+  dvp.dp_timeout = timeout;
+  int ret=ioctl(d_devpollfd, DP_POLL, &dvp);
   gettimeofday(now,0); // MANDATORY!
-  
-  if(ret < 0 && errno!=EINTR)
+
+  if(ret < 0 && errno!=EINTR) {
+    delete[] dvp.dp_fds;
     throw FDMultiplexerException("/dev/poll returned error: "+stringerror());
+  }
 
-  if(ret < 1) // thanks AB!
+  if(ret < 1) { // thanks AB!
+    delete[] dvp.dp_fds;
     return 0;
+  }
 
   d_inrun=true;
   for(int n=0; n < ret; ++n) {
@@ -122,7 +171,7 @@ int DevPollFDMultiplexer::run(struct timeval* now)
   }
   delete[] dvp.dp_fds;
   d_inrun=false;
-  return 0;
+  return ret;
 }
 
 #if 0