guile-commits
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Guile-commits] 06/06: Reduce redundant 'close' calls when forking on so


From: Ludovic Courtès
Subject: [Guile-commits] 06/06: Reduce redundant 'close' calls when forking on some systems.
Date: Thu, 12 Jan 2023 16:51:01 -0500 (EST)

civodul pushed a commit to branch wip-posix-spawn
in repository guile.

commit f674ef6ccc3b8ac4ae160c05dfdeb4bfb72468b5
Author: Andrew Whatson <whatson@gmail.com>
AuthorDate: Fri Dec 23 00:27:22 2022 +0100

    Reduce redundant 'close' calls when forking on some systems.
    
    Some systems provide "/proc/self/fd" which is a directory containing an
    entry for each open file descriptor in the current process.  We use this
    to limit the number of close() calls needed to ensure file descriptors
    aren't leaked to the child process when forking.
    
    * libguile/posix.c (close_inherited_fds_slow):
    (close_inherited_fds): New static helper functions.
    (scm_spawn_process): Attempt to close inherited file descriptors
    efficiently using 'close_inherited_fds', falling back to the brute-force
    approach in 'close_inherited_fds_slow'.
---
 libguile/posix.c | 41 ++++++++++++++++++++++++++++++++++++++---
 1 file changed, 38 insertions(+), 3 deletions(-)

diff --git a/libguile/posix.c b/libguile/posix.c
index 38f938404..79f96192f 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)



reply via email to

[Prev in Thread] Current Thread [Next in Thread]