guile-commits
[Top][All Lists]
Advanced

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

[Guile-commits] 06/07: fixup! Make system* and piped-process internally


From: Ludovic Courtès
Subject: [Guile-commits] 06/07: fixup! Make system* and piped-process internally use spawn.
Date: Fri, 23 Dec 2022 05:45:31 -0500 (EST)

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

commit d4ece4b74d9920bd07e5bfe875ce85abe623f98e
Author: Ludovic Courtès <ludo@gnu.org>
AuthorDate: Fri Dec 23 11:26:55 2022 +0100

    fixup! Make system* and piped-process internally use spawn.
    
    Avoid extra 'fork' upon error in 'system*'.
---
 libguile/posix.c | 117 ++++++++++++++++++++++++++++++++++---------------------
 1 file changed, 72 insertions(+), 45 deletions(-)

diff --git a/libguile/posix.c b/libguile/posix.c
index de2a31aae..79b066bb3 100644
--- a/libguile/posix.c
+++ b/libguile/posix.c
@@ -78,6 +78,7 @@
 #include "threads.h"
 #include "values.h"
 #include "vectors.h"
+#include "verify.h"
 #include "version.h"
 
 #if (SCM_ENABLE_DEPRECATED == 1)
@@ -96,6 +97,13 @@
 # define WIFEXITED(stat_val) (((stat_val) & 255) == 0)
 #endif
 
+#ifndef W_EXITCODE
+/* Macro for constructing a status value.  Found in glibc.  */
+# define W_EXITCODE(ret, sig)   ((ret) << 8 | (sig))
+#endif
+verify (WEXITSTATUS (W_EXITCODE (127, 0)) == 127);
+
+
 #include <signal.h>
 
 #ifdef HAVE_GRP_H
@@ -1424,15 +1432,14 @@ SCM_DEFINE (scm_spawn_process, "spawn*", 5, 0, 0,
 #undef FUNC_NAME
 
 #ifdef HAVE_FORK
-static SCM
-scm_piped_process (SCM prog, SCM args, SCM from, SCM to)
+static int
+piped_process (pid_t *pid, SCM prog, SCM args, SCM from, SCM to)
 #define FUNC_NAME "piped-process"
 {
   int reading, writing;
   int c2p[2]; /* Child to parent.  */
   int p2c[2]; /* Parent to child.  */
   int in = -1, out = -1, err = -1;
-  int pid;
   char *exec_file;
   char **exec_argv;
   char **exec_env = environ;
@@ -1468,48 +1475,57 @@ scm_piped_process (SCM prog, SCM args, SCM from, SCM to)
       in = SCM_FPORT_FDES (port);
   }
 
-  pid = do_spawn (exec_file, exec_argv, exec_env, in, out, err);
-  int errno_save = errno;
-
-  if (pid == -1)
-    {
-      /* TODO This is a compatibility shim until the next major release */
-      switch (errno)
-        {
-          /* If the error seemingly comes from fork */
-        case EAGAIN:
-        case ENOMEM:
-        case ENOSYS:
-          free (exec_file);
-
-          if (reading)
-            close (c2p[0]);
-          if (writing)
-            close (p2c[1]);
-
-          errno = errno_save;
-          SCM_SYSERROR;
-          break;
-
-        default:
-          /* Else create a dummy process that exits with value 127 */
-          dprintf (err, "In execvp of %s: %s\n", exec_file,
-                   strerror (errno_save));
-          pid = fork ();
-          if (pid == -1)
-            SCM_SYSERROR;
-          if (pid == 0)
-            _exit (127);
-        }
-    }
-
-  free (exec_file);
+  *pid = do_spawn (exec_file, exec_argv, exec_env, in, out, err);
+  int errno_save = (*pid < 0) ? errno : 0;
 
   if (reading)
     close (c2p[1]);
   if (writing)
     close (p2c[0]);
 
+  if (*pid == -1)
+    switch (errno_save)
+      {
+        /* Errors that seemingly come from fork.  */
+      case EAGAIN:
+      case ENOMEM:
+      case ENOSYS:
+        errno = err;
+        free (exec_file);
+        SCM_SYSERROR;
+        break;
+
+      default:    /* ENOENT, etc. */
+        /* Create a dummy process that exits with value 127.  */
+        dprintf (err, "In execvp of %s: %s\n", exec_file,
+                 strerror (errno_save));
+      }
+
+  free (exec_file);
+
+  return errno_save;
+}
+#undef FUNC_NAME
+
+static SCM
+scm_piped_process (SCM prog, SCM args, SCM from, SCM to)
+#define FUNC_NAME "piped-process"
+{
+  pid_t pid;
+
+  (void) piped_process (&pid, prog, args, from, to);
+  if (pid == -1)
+    {
+      /* Create a dummy process that exits with value 127 to mimic the
+         previous fork + exec implementation.  TODO: This is a
+         compatibility shim to remove in the next stable series.  */
+      pid = fork ();
+      if (pid == -1)
+        SCM_SYSERROR;
+      if (pid == 0)
+        _exit (127);
+    }
+
   return scm_from_int (pid);
 }
 #undef FUNC_NAME
@@ -1555,8 +1571,9 @@ SCM_DEFINE (scm_system_star, "system*", 0, 0, 1,
 "Example: (system* \"echo\" \"foo\" \"bar\")")
 #define FUNC_NAME s_scm_system_star
 {
-  SCM prog, pid;
-  int status, wait_result;
+  SCM prog;
+  pid_t pid;
+  int err, status, wait_result;
 
   if (scm_is_null (args))
     SCM_WRONG_NUM_ARGS ();
@@ -1574,10 +1591,20 @@ SCM_DEFINE (scm_system_star, "system*", 0, 0, 1,
                          SCM_UNDEFINED);
 #endif
 
-  pid = scm_piped_process (prog, args, SCM_UNDEFINED, SCM_UNDEFINED);
-  SCM_SYSCALL (wait_result = waitpid (scm_to_int (pid), &status, 0));
-  if (wait_result == -1)
-    SCM_SYSERROR;
+  err = piped_process (&pid, prog, args,
+                       SCM_UNDEFINED, SCM_UNDEFINED);
+  if (err != 0)
+    /* ERR might be ENOENT or similar.  For backward compatibility with
+       the previous implementation based on fork + exec, pretend the
+       child process exited with code 127.  TODO: Remove this
+       compatibility shim in the next stable series.  */
+    status = W_EXITCODE (127, 0);
+  else
+    {
+      SCM_SYSCALL (wait_result = waitpid (pid, &status, 0));
+      if (wait_result == -1)
+        SCM_SYSERROR;
+    }
 
   scm_dynwind_end ();
 



reply via email to

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