Use the closefrom system call if available to close all fds.
authorTaylor R Campbell <campbell@mumble.net>
Sun, 10 Apr 2011 19:21:06 +0000 (19:21 +0000)
committerTaylor R Campbell <campbell@mumble.net>
Sun, 10 Apr 2011 21:35:03 +0000 (21:35 +0000)
If not available, fall back to fcntl(F_CLOSEM); if that's not
available, fall back to closing all fds up to and including
fcntl(F_MAXFD); if that's not available, fall back to closing all
fds below UX_SC_OPEN_MAX like before.

Each case tested under NetBSD by running runtime/test-process.scm,
evaluating (RUN-SHELL-COMMAND "ls"), and ktracing Scheme during

   (RUN-SUBPROCESS-IN-FOREGROUND "/usr/bin/true" '#("true") '#())

with `ktrace -d -i' to make sure that it uses the right sequence of
system calls.

src/microcode/configure.ac
src/microcode/ux.c
src/microcode/ux.h
src/microcode/uxproc.c

index 3a8501280af25a135328a2f8a0b54de256c2f63f..f913ec9bf20904741ecda500a867c45cd5e8c36b 100644 (file)
@@ -706,7 +706,7 @@ AC_FUNC_UTIME_NULL
 AC_FUNC_VFORK
 AC_FUNC_VPRINTF
 AC_FUNC_WAIT3
-AC_CHECK_FUNCS([clock_gettime ctermid])
+AC_CHECK_FUNCS([clock_gettime closefrom ctermid])
 AC_CHECK_FUNCS([dup2])
 AC_CHECK_FUNCS([fcntl fdatasync feclearexcept fedisableexcept feenableexcept])
 AC_CHECK_FUNCS([fegetenv fegetexcept fegetexceptflag fegetround feholdexcept])
index a8f70d54b60dd0ef4fb249017680eb39fae250e0..de6d32752bf13d17a8cf235d602da51c8886e3d5 100644 (file)
@@ -624,6 +624,33 @@ fpathconf (int filedes, int parameter)
 }
 #endif /* EMULATE_FPATHCONF */
 \f
+#ifdef EMULATE_CLOSEFROM
+
+int
+UX_closefrom (int fd)
+{
+#if ((defined (HAVE_FCNTL)) && (defined (F_CLOSEM)))
+  return (UX_fcntl (fd, F_CLOSEM));
+#elif ((defined (HAVE_FCNTL)) && (defined (F_MAXFD)))
+  int max_fd = (UX_fcntl ((-1), F_MAXFD));
+  int status;
+  if (max_fd < 0) return (max_fd);
+  while (fd <= max_fd)
+    if (((status = (UX_close (fd++))) < 0) && (errno != EBADF))
+      return (status);
+  return (0);
+#else
+  int fd_limit = (UX_SC_OPEN_MAX ());
+  int status;
+  while (fd < fd_limit)
+    if (((status = (UX_close (fd++))) < 0) && (errno != EBADF))
+      return (status);
+  return (0);
+#endif
+}
+
+#endif
+\f
 void *
 OS_malloc_init (size_t size)
 {
index 13c9147edcf0c26d67401682462dade0ec8babcd..c496d14ac3eb643d4b13b555c9607e65f5188d0e 100644 (file)
@@ -621,6 +621,13 @@ typedef RETSIGTYPE Tsignal_handler_result;
    extern unsigned long UX_getpagesize (void);
 #  define EMULATE_GETPAGESIZE
 #endif
+
+#ifdef HAVE_CLOSEFROM
+#  define UX_closefrom closefrom
+#else
+   extern int UX_closefrom (int);
+#  define EMULATE_CLOSEFROM
+#endif
 \f
 /* poll is somewhat busted on Mac OSX 10.4 (Tiger), so use select.  */
 #ifdef __APPLE__
index db4c7fb0480dee0207ac740e4b1bd034369ce1ec..daf0fd73a1209802cf72a21f16d3538c3d8a9e1e 100644 (file)
@@ -420,20 +420,17 @@ OS_make_subprocess (const char * filename,
          goto kill_child;
       }
   }
-  {
-    /* Close all other file descriptors. */
-    int open_max = (UX_SC_OPEN_MAX ());
-    int fd;
-    for (fd = 0; (fd < open_max); fd += 1)
-      if ((fd == STDIN_FILENO)
-         ? (channel_in_type == process_channel_type_none)
-         : (fd == STDOUT_FILENO)
-         ? (channel_out_type == process_channel_type_none)
-         : (fd == STDERR_FILENO)
-         ? (channel_err_type == process_channel_type_none)
-         : 1)
-       (void) UX_close (fd);
-  }
+
+  /* Close all file descriptors not used by the child.  */
+  /* FIXME: Handle EINTR?  */
+  if (channel_in_type == process_channel_type_none)
+    if ((UX_close (STDIN_FILENO)) < 0) goto kill_child;
+  if (channel_out_type == process_channel_type_none)
+    if ((UX_close (STDOUT_FILENO)) < 0) goto kill_child;
+  if (channel_err_type == process_channel_type_none)
+    if ((UX_close (STDERR_FILENO)) < 0) goto kill_child;
+  /* Assumption: STDIN_FILENO = 0, STDOUT_FILENO = 1, STDERR_FILENO = 2.  */
+  if ((UX_closefrom (3)) < 0) goto kill_child;
 
   /* Put the signal mask and handlers in a normal state.  */
   UX_initialize_child_signals ();