cloexec: make use of pipe2(O_CLOEXEC) when available
authorLennart Poettering <lennart@poettering.net>
Wed, 22 Apr 2009 02:45:46 +0000 (04:45 +0200)
committerLennart Poettering <lennart@poettering.net>
Wed, 20 May 2009 00:09:31 +0000 (02:09 +0200)
This should fix another CLOEXEC race.

configure.in
dbus/dbus-spawn.c

index 62312eb..7e0c7d5 100644 (file)
@@ -816,6 +816,8 @@ fi
 
 AC_CHECK_FUNCS(getpeerucred getpeereid)
 
+AC_CHECK_FUNCS(pipe2)
+
 #### Abstract sockets
 
 if test x$enable_abstract_sockets = xauto; then
index b0b843e..fa2e15c 100644 (file)
@@ -21,6 +21,9 @@
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  *
  */
+
+#include <config.h>
+
 #include "dbus-spawn.h"
 #include "dbus-sysdeps-unix.h"
 #include "dbus-internals.h"
@@ -805,9 +808,25 @@ static dbus_bool_t
 make_pipe (int         p[2],
            DBusError  *error)
 {
+  int retval;
+
+#ifdef HAVE_PIPE2
+  dbus_bool_t cloexec_done;
+
+  retval = pipe2 (p, O_CLOEXEC);
+  cloexec_done = retval >= 0;
+
+  /* Check if kernel seems to be too old to know pipe2(). We assume
+     that if pipe2 is available, O_CLOEXEC is too.  */
+  if (retval < 0 && errno == ENOSYS)
+#endif
+    {
+      retval = pipe(p);
+    }
+
   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
-  
-  if (pipe (p) < 0)
+
+  if (retval < 0)
     {
       dbus_set_error (error,
                      DBUS_ERROR_SPAWN_FAILED,
@@ -816,6 +835,14 @@ make_pipe (int         p[2],
       return FALSE;
     }
 
+#ifdef HAVE_PIPE2
+  if (!cloexec_done)
+#endif
+    {
+      _dbus_fd_set_close_on_exec (p[0]);
+      _dbus_fd_set_close_on_exec (p[1]);
+    }
+
   return TRUE;
 }
 
@@ -1117,9 +1144,6 @@ _dbus_spawn_async_with_babysitter (DBusBabysitter          **sitter_p,
   if (!make_pipe (child_err_report_pipe, error))
     goto cleanup_and_fail;
 
-  _dbus_fd_set_close_on_exec (child_err_report_pipe[READ_END]);
-  _dbus_fd_set_close_on_exec (child_err_report_pipe[WRITE_END]);
-
   if (!_dbus_full_duplex_pipe (&babysitter_pipe[0], &babysitter_pipe[1], TRUE, error))
     goto cleanup_and_fail;