cloexec: set FD_CLOEXEC for all full duplex pipes
authorLennart Poettering <lennart@poettering.net>
Wed, 22 Apr 2009 02:22:51 +0000 (04:22 +0200)
committerLennart Poettering <lennart@poettering.net>
Wed, 20 May 2009 00:09:31 +0000 (02:09 +0200)
All users of full duplex pipes enable FD_CLOEXEC later anyway so let's
just do it as part of _dbus_full_duplex_pipe. By side effect this allows
to make use of SOCK_CLOEXEC which fixes a race when forking/execing from
a different thread at the same time as we ar in this function.

bus/main.c
dbus/dbus-server-debug-pipe.c
dbus/dbus-spawn.c
dbus/dbus-sysdeps-unix.c

index 51538fe7d3c9cd2333c8146a1e8e5ecf0cdafbfa..d86825a5005b10ba199de2ae83711754969052b8 100644 (file)
@@ -208,9 +208,6 @@ setup_reload_pipe (DBusLoop *loop)
       exit (1);
     }
 
-  _dbus_fd_set_close_on_exec (reload_pipe[0]);
-  _dbus_fd_set_close_on_exec (reload_pipe[1]);
-
   watch = _dbus_watch_new (reload_pipe[RELOAD_READ_END],
                           DBUS_WATCH_READABLE, TRUE,
                           handle_reload_watch, NULL, NULL);
index 24b0ce3429bb9d517b23af6594fc330a4606e408..b59f7491cc15fb20ca9bccb9b70a5d79f2ea06e5 100644 (file)
@@ -253,9 +253,6 @@ _dbus_transport_debug_pipe_new (const char     *server_name,
       return NULL;
     }
 
-  _dbus_fd_set_close_on_exec (client_fd);
-  _dbus_fd_set_close_on_exec (server_fd);
-  
   client_transport = _dbus_transport_new_for_socket (client_fd,
                                                      NULL, &address);
   if (client_transport == NULL)
index f4e3b587a23da841126f3191f2be59e7e30fd48e..b0b843ead9583979380b5ee19b6d0483bd436524 100644 (file)
@@ -1123,9 +1123,6 @@ _dbus_spawn_async_with_babysitter (DBusBabysitter          **sitter_p,
   if (!_dbus_full_duplex_pipe (&babysitter_pipe[0], &babysitter_pipe[1], TRUE, error))
     goto cleanup_and_fail;
 
-  _dbus_fd_set_close_on_exec (babysitter_pipe[0]);
-  _dbus_fd_set_close_on_exec (babysitter_pipe[1]);
-
   /* Setting up the babysitter is only useful in the parent,
    * but we don't want to run out of memory and fail
    * after we've already forked, since then we'd leak
index 597398bbb3121424207e315db6edb6c73bd64080..8b225e7e7530c5cdd74bdbe63b98c447c26ca124 100644 (file)
@@ -3067,6 +3067,8 @@ _dbus_print_backtrace (void)
  * Creates a full-duplex pipe (as in socketpair()).
  * Sets both ends of the pipe nonblocking.
  *
+ * Marks both file descriptors as close-on-exec
+ *
  * @todo libdbus only uses this for the debug-pipe server, so in
  * principle it could be in dbus-sysdeps-util.c, except that
  * dbus-sysdeps-util.c isn't in libdbus when tests are enabled and the
@@ -3086,16 +3088,37 @@ _dbus_full_duplex_pipe (int        *fd1,
 {
 #ifdef HAVE_SOCKETPAIR
   int fds[2];
+  int retval;
 
-  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
-  
-  if (socketpair (AF_UNIX, SOCK_STREAM, 0, fds) < 0)
+#ifdef SOCK_CLOEXEC
+  dbus_bool_t cloexec_done;
+
+  retval = socketpair(AF_UNIX, SOCK_STREAM|SOCK_CLOEXEC, 0, fds);
+  cloexec_done = retval >= 0;
+
+  if (retval < 0 && errno == EINVAL)
+#endif
+    {
+      retval = socketpair(AF_UNIX, SOCK_STREAM, 0, fds);
+    }
+
+  if (retval < 0)
     {
       dbus_set_error (error, _dbus_error_from_errno (errno),
                       "Could not create full-duplex pipe");
       return FALSE;
     }
 
+  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
+
+#ifdef SOCK_CLOEXEC
+  if (!cloexec_done)
+#endif
+    {
+      _dbus_fd_set_close_on_exec (fds[0]);
+      _dbus_fd_set_close_on_exec (fds[1]);
+    }
+
   if (!blocking &&
       (!_dbus_set_fd_nonblocking (fds[0], NULL) ||
        !_dbus_set_fd_nonblocking (fds[1], NULL)))