tevent: Set FD_CLOEXEC on epoll handle
authorSumit Bose <sbose@redhat.com>
Thu, 11 Aug 2011 10:30:48 +0000 (12:30 +0200)
committerSimo Sorce <idra@samba.org>
Thu, 11 Aug 2011 18:38:53 +0000 (14:38 -0400)
If an application using libtevent starts a new process the epoll file descriptor
is leaked to the new process if the event context is not freed explicitly. By
setting FD_CLOEXEC this is not needed anymore.

Signed-off-by: Simo Sorce <idra@samba.org>
lib/tevent/tevent_epoll.c
lib/tevent/tevent_standard.c
lib/tevent/tevent_util.c
lib/tevent/tevent_util.h

index 3ab828395586f6a8ce1d4563678b58ad24cd7ec7..33e1d3f20fffe6b6c0a970c9516591dfb78375c0 100644 (file)
@@ -78,11 +78,20 @@ static int epoll_ctx_destructor(struct epoll_event_context *epoll_ev)
 static int epoll_init_ctx(struct epoll_event_context *epoll_ev)
 {
        epoll_ev->epoll_fd = epoll_create(64);
-       epoll_ev->pid = getpid();
-       talloc_set_destructor(epoll_ev, epoll_ctx_destructor);
        if (epoll_ev->epoll_fd == -1) {
+               tevent_debug(epoll_ev->ev, TEVENT_DEBUG_FATAL,
+                            "Failed to create epoll handle.\n");
                return -1;
        }
+
+       if (!ev_set_close_on_exec(epoll_ev->epoll_fd)) {
+               tevent_debug(epoll_ev->ev, TEVENT_DEBUG_WARNING,
+                            "Failed to set close-on-exec, file descriptor may be leaked to children.\n");
+       }
+
+       epoll_ev->pid = getpid();
+       talloc_set_destructor(epoll_ev, epoll_ctx_destructor);
+
        return 0;
 }
 
@@ -108,6 +117,12 @@ static void epoll_check_reopen(struct epoll_event_context *epoll_ev)
                             "Failed to recreate epoll handle after fork\n");
                return;
        }
+
+       if (!ev_set_close_on_exec(epoll_ev->epoll_fd)) {
+               tevent_debug(epoll_ev->ev, TEVENT_DEBUG_WARNING,
+                            "Failed to set close-on-exec, file descriptor may be leaked to children.\n");
+       }
+
        epoll_ev->pid = getpid();
        for (fde=epoll_ev->ev->fd_events;fde;fde=fde->next) {
                epoll_add_event(epoll_ev, fde);
index 35f7ded9b703792e4abfdf389bf9c74b0e1bde4e..e2ca44f9c2950a5da998d6aa5d40720d1fd7a9d9 100644 (file)
@@ -100,6 +100,17 @@ static int epoll_ctx_destructor(struct std_event_context *std_ev)
 static void epoll_init_ctx(struct std_event_context *std_ev)
 {
        std_ev->epoll_fd = epoll_create(64);
+       if (std_ev->epoll_fd == -1) {
+               tevent_debug(std_ev->ev, TEVENT_DEBUG_FATAL,
+                            "Failed to create epoll handle.\n");
+               return;
+       }
+
+       if (!ev_set_close_on_exec(std_ev->epoll_fd)) {
+               tevent_debug(std_ev->ev, TEVENT_DEBUG_WARNING,
+                            "Failed to set close-on-exec, file descriptor may be leaked to children.\n");
+       }
+
        std_ev->pid = getpid();
        talloc_set_destructor(std_ev, epoll_ctx_destructor);
 }
@@ -126,6 +137,12 @@ static void epoll_check_reopen(struct std_event_context *std_ev)
                             "Failed to recreate epoll handle after fork\n");
                return;
        }
+
+       if (!ev_set_close_on_exec(std_ev->epoll_fd)) {
+               tevent_debug(std_ev->ev, TEVENT_DEBUG_WARNING,
+                            "Failed to set close-on-exec, file descriptor may be leaked to children.\n");
+       }
+
        std_ev->pid = getpid();
        for (fde=std_ev->ev->fd_events;fde;fde=fde->next) {
                epoll_add_event(std_ev, fde);
index f78cd8f707ded54e65408eb07d18d38a3fe52142..16af8f3b908d8c0502a18403ac70a0b476df1419 100644 (file)
@@ -88,3 +88,20 @@ int ev_set_blocking(int fd, bool set)
        return fcntl( fd, F_SETFL, val);
 #undef FLAG_TO_SET
 }
+
+bool ev_set_close_on_exec(int fd)
+{
+#ifdef FD_CLOEXEC
+       int val;
+
+       val = fcntl(fd, F_GETFD, 0);
+       if (val >= 0) {
+               val |= FD_CLOEXEC;
+               val = fcntl(fd, F_SETFD, val);
+               if (val != -1) {
+                       return true;
+               }
+       }
+#endif
+       return false;
+}
index 46a4506dac4ec74edab1ceea1a3c423742766c77..311be604a0808bce8ad9e0d2bcabdc04531dc201 100644 (file)
@@ -183,6 +183,7 @@ do { \
 const char **ev_str_list_add(const char **list, const char *s);
 int ev_set_blocking(int fd, bool set);
 size_t ev_str_list_length(const char **list);
+bool ev_set_close_on_exec(int fd);
 
 /* Defined here so we can build against older talloc versions that don't
  * have this define yet. */