diff options
-rw-r--r-- | NEWS | 2 | ||||
-rw-r--r-- | libguile/posix.c | 41 |
2 files changed, 40 insertions, 3 deletions
@@ -99,6 +99,8 @@ Disassembler output now includes the name of intrinsics next to each mode was set explicitly. However, this is not the case. ** 'system*' honors output/error port redirects (https://bugs.gnu.org/52835) +** 'open-input-pipe' & co. are now much faster + (https://bugs.gnu.org/59321) Changes in 3.0.8 (since 3.0.7) diff --git a/libguile/posix.c b/libguile/posix.c index 8d1981c20..ae9792890 100644 --- a/libguile/posix.c +++ b/libguile/posix.c @@ -24,6 +24,7 @@ # include <config.h> #endif +#include <dirent.h> #include <errno.h> #include <fcntl.h> #include <stdio.h> @@ -1317,6 +1318,41 @@ SCM_DEFINE (scm_fork, "primitive-fork", 0, 0, 0, #undef FUNC_NAME #endif /* HAVE_FORK */ +static void +close_inherited_fds_slow (posix_spawn_file_actions_t *actions, int max_fd) +{ + while (--max_fd > 2) + posix_spawn_file_actions_addclose (actions, max_fd); +} + +static void +close_inherited_fds (posix_spawn_file_actions_t *actions, int max_fd) +{ + DIR *dirp; + struct dirent *d; + int fd; + + /* Try to use the platform-specific list of open file descriptors, so + we don't need to use the brute force approach. */ + dirp = opendir ("/proc/self/fd"); + + if (dirp == NULL) + return close_inherited_fds_slow (actions, max_fd); + + while ((d = readdir (dirp)) != NULL) + { + fd = atoi (d->d_name); + + /* Skip "." and "..", garbage entries, stdin/stdout/stderr. */ + if (fd <= 2) + continue; + + posix_spawn_file_actions_addclose (actions, fd); + } + + closedir (dirp); +} + static pid_t do_spawn (char *exec_file, char **exec_argv, char **exec_env, int in, int out, int err, int spawnp) @@ -1341,7 +1377,7 @@ do_spawn (char *exec_file, char **exec_argv, char **exec_env, int free_fd_slots = 0; int fd_slot[3]; - for (int fdnum = 3;free_fd_slots < 3 && fdnum < max_fd;fdnum++) + for (int fdnum = 3; free_fd_slots < 3 && fdnum < max_fd; fdnum++) { if (fdnum != in && fdnum != out && fdnum != err) { @@ -1360,8 +1396,7 @@ do_spawn (char *exec_file, char **exec_argv, char **exec_env, posix_spawn_file_actions_adddup2 (&actions, fd_slot[1], 1); posix_spawn_file_actions_adddup2 (&actions, fd_slot[2], 2); - while (--max_fd > 2) - posix_spawn_file_actions_addclose (&actions, max_fd); + close_inherited_fds (&actions, max_fd); int res = -1; if (spawnp) |