Backported to glibc 2.8
[lttng-tools.git] / src / common / compat / poll.h
index 9e889767f8321a05ea23f97c211086cf0c6e3836..f892c832333eb10bdfcc4cf64d66918c17d3ab02 100644 (file)
@@ -52,6 +52,8 @@ static inline void __lttng_poll_free(void *events)
 #ifdef HAVE_EPOLL
 #include <sys/epoll.h>
 #include <stdio.h>
+#include <features.h>
+#include <common/compat/fcntl.h>
 
 /* See man epoll(7) for this define path */
 #define COMPAT_EPOLL_PROC_PATH "/proc/sys/fs/epoll/max_user_watches"
@@ -71,7 +73,17 @@ enum {
        LPOLLNVAL = EPOLLHUP,
        LPOLLRDHUP = EPOLLRDHUP,
        /* Close on exec feature of epoll */
+#if __GLIBC_PREREQ(2, 9)
        LTTNG_CLOEXEC = EPOLL_CLOEXEC,
+#else
+       /*
+        * EPOLL_CLOEXEC was added in glibc 2.8 (usually used in conjunction with
+        * epoll_create1(..)), but since neither EPOLL_CLOEXEC exists nor
+        * epoll_create1(..), we set it to FD_CLOEXEC so that we can pass it
+        * directly to fcntl(..) instead.
+        */
+       LTTNG_CLOEXEC = FD_CLOEXEC,
+#endif
 };
 
 struct compat_epoll_event {
@@ -115,6 +127,27 @@ extern int compat_epoll_create(struct lttng_poll_event *events,
 #define lttng_poll_create(events, size, flags) \
        compat_epoll_create(events, size, flags)
 
+#if __GLIBC_PREREQ(2, 9)
+static inline int compat_glibc_epoll_create(int size __attribute__((unused)),
+               int flags)
+{
+       return epoll_create1(flags);
+}
+#else
+static inline int compat_glibc_epoll_create(int size, int flags)
+{
+       /*
+        * epoll_create1 was added in glibc 2.9, but unfortunatly reverting to
+        * epoll_create(..) also means that we lose the possibility to
+        * directly set the EPOLL_CLOEXEC, so try and do it anyway but through
+        * fcntl(..).
+        */
+       int efd = epoll_create(size);
+       assert(fcntl(efd, F_SETFD, flags) != -1);
+       return efd;
+}
+#endif
+
 /*
  * Wait on epoll set with the number of fd registered to the lttng_poll_event
  * data structure (events).
@@ -158,6 +191,17 @@ static inline void lttng_poll_reset(struct lttng_poll_event *events)
        }
 }
 
+/*
+ * Initialize an already allocated poll event data structure. For epoll(), the
+ * epfd is set to -1 to indicate that it's not usable.
+ */
+static inline void lttng_poll_init(struct lttng_poll_event *events)
+{
+       memset(events, 0, sizeof(struct lttng_poll_event));
+       /* Set fd to -1 so if clean before created, we don't close 0. */
+       events->epfd = -1;
+}
+
 /*
  * Clean the events structure of a lttng_poll_event. It's the caller
  * responsability to free the lttng_poll_event memory.
@@ -166,13 +210,18 @@ static inline void lttng_poll_clean(struct lttng_poll_event *events)
 {
        int ret;
 
-       if (events) {
+       if (!events) {
+               return;
+       }
+
+       if (events->epfd >= 0) {
                ret = close(events->epfd);
                if (ret) {
                        perror("close");
                }
-               __lttng_poll_free((void *) events->events);
        }
+
+       __lttng_poll_free((void *) events->events);
 }
 
 #else  /* HAVE_EPOLL */
@@ -312,6 +361,14 @@ extern void compat_poll_set_max_size(void);
 static inline void lttng_poll_reset(struct lttng_poll_event *events)
 {}
 
+/*
+ * Initialize an already allocated poll event data structure.
+ */
+static inline void lttng_poll_init(struct lttng_poll_event *events)
+{
+       memset(events, 0, sizeof(struct lttng_poll_event));
+}
+
 /*
  * Clean the events structure of a lttng_poll_event. It's the caller
  * responsability to free the lttng_poll_event memory.
This page took 0.025149 seconds and 4 git commands to generate.