Use epoll in a backwards-compatible way on Linux < 2.6.27
authorSimon McVittie <simon.mcvittie@collabora.co.uk>
Thu, 3 Feb 2011 17:18:09 +0000 (17:18 +0000)
committerSimon McVittie <simon.mcvittie@collabora.co.uk>
Mon, 13 Jun 2011 16:30:47 +0000 (17:30 +0100)
Bug: https://bugs.freedesktop.org/show_bug.cgi?id=33337
Bug-NB: NB#197191
Bug-NB: NB#225019

configure.ac
dbus/dbus-socket-set-epoll.c

index d3fba82..2c4a115 100644 (file)
@@ -999,6 +999,9 @@ fi
 
 AM_CONDITIONAL(DBUS_BUS_ENABLE_DNOTIFY_ON_LINUX, test x$have_dnotify = xyes)
 
+# For simplicity, we require the userland API for epoll_create1 at
+# compile-time (glibc 2.9), but we'll run on kernels that turn out
+# not to have it at runtime.
 AC_ARG_ENABLE([epoll],
               [AS_HELP_STRING([--enable-epoll],[use epoll(4) on Linux])],
               [enable_epoll=$enableval], [enable_epoll=auto])
index 430a857..4cd9a56 100644 (file)
@@ -33,6 +33,7 @@
 #endif
 
 #include <errno.h>
+#include <fcntl.h>
 #include <sys/epoll.h>
 #include <unistd.h>
 
@@ -81,6 +82,21 @@ _dbus_socket_set_epoll_new (void)
 
   if (self->epfd == -1)
     {
+      int flags;
+
+      /* the size hint is ignored unless you have a rather old kernel,
+       * but must be positive on some versions, so just pick something
+       * arbitrary; it's a hint, not a limit */
+      self->epfd = epoll_create (42);
+
+      flags = fcntl (self->epfd, F_GETFD, 0);
+
+      if (flags != -1)
+        fcntl (self->epfd, F_SETFD, flags | FD_CLOEXEC);
+    }
+
+  if (self->epfd == -1)
+    {
       socket_set_epoll_free ((DBusSocketSet *) self);
       return NULL;
     }
@@ -252,8 +268,11 @@ socket_set_epoll_remove (DBusSocketSet  *set,
 {
   DBusSocketSetEpoll *self = socket_set_epoll_cast (set);
   int err;
+  /* Kernels < 2.6.9 require a non-NULL struct pointer, even though its
+   * contents are ignored */
+  struct epoll_event dummy = { 0 };
 
-  if (epoll_ctl (self->epfd, EPOLL_CTL_DEL, fd, NULL) == 0)
+  if (epoll_ctl (self->epfd, EPOLL_CTL_DEL, fd, &dummy) == 0)
     return;
 
   err = errno;