From: Taylor R Campbell Date: Sun, 10 Apr 2011 19:21:06 +0000 (+0000) Subject: Use the closefrom system call if available to close all fds. X-Git-Tag: 20110426-Gtk~2^2~7 X-Git-Url: https://birchwood-abbey.net/git?a=commitdiff_plain;h=43be79e71144d5be6ac7dbe6a26c5ef32266e779;p=mit-scheme.git Use the closefrom system call if available to close all fds. 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. --- diff --git a/src/microcode/configure.ac b/src/microcode/configure.ac index 3a8501280..f913ec9bf 100644 --- a/src/microcode/configure.ac +++ b/src/microcode/configure.ac @@ -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]) diff --git a/src/microcode/ux.c b/src/microcode/ux.c index a8f70d54b..de6d32752 100644 --- a/src/microcode/ux.c +++ b/src/microcode/ux.c @@ -624,6 +624,33 @@ fpathconf (int filedes, int parameter) } #endif /* EMULATE_FPATHCONF */ +#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 + void * OS_malloc_init (size_t size) { diff --git a/src/microcode/ux.h b/src/microcode/ux.h index 13c9147ed..c496d14ac 100644 --- a/src/microcode/ux.h +++ b/src/microcode/ux.h @@ -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 /* poll is somewhat busted on Mac OSX 10.4 (Tiger), so use select. */ #ifdef __APPLE__ diff --git a/src/microcode/uxproc.c b/src/microcode/uxproc.c index db4c7fb04..daf0fd73a 100644 --- a/src/microcode/uxproc.c +++ b/src/microcode/uxproc.c @@ -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 ();