Pádraig Brady <[email protected]> writes:

>>> where I noted glibc's implementation was just becoming usable,
>>> which definitely should be the case by now.
>> What was wrong with it previously? As far as I can tell, before
>> glibc-2.24 posix_spawn just did fork/vfork + exec. Were there problems
>> with that implementation or some issues with the earlier clone versions?
>
> I was thinking of https://sourceware.org/PR10354

Oh, in that case we can use the POSIX_SPAWN_USEVFORK. Attached an
example patch for 'install'.

Collin

>From a18dcfe304ea5407f47c68e501b1f58c92978ced Mon Sep 17 00:00:00 2001
Message-ID: <a18dcfe304ea5407f47c68e501b1f58c92978ced.1760912824.git.collin.fu...@gmail.com>
From: Collin Funk <[email protected]>
Date: Sun, 19 Oct 2025 15:22:17 -0700
Subject: [PATCH] install: prefer posix_spawnp to fork and execlp

* bootstrap.conf (gnulib_modules): Add posix_spawnattr_destroy,
posix_spawnattr_init, posix_spawnattr_setflags, and posix_spawnp.
* src/install.c (strip): Use posix_spawnp instead of fork and execlp.
---
 bootstrap.conf |  4 ++++
 src/install.c  | 62 +++++++++++++++++++++++++++++++-------------------
 2 files changed, 43 insertions(+), 23 deletions(-)

diff --git a/bootstrap.conf b/bootstrap.conf
index f470aa48b..c5f46242b 100644
--- a/bootstrap.conf
+++ b/bootstrap.conf
@@ -211,6 +211,10 @@ gnulib_modules="
   pipe-posix
   pipe2
   posix-shell
+  posix_spawnattr_destroy
+  posix_spawnattr_init
+  posix_spawnattr_setflags
+  posix_spawnp
   posixtm
   posixver
   priv-set
diff --git a/src/install.c b/src/install.c
index 43c7729af..d65fa85f3 100644
--- a/src/install.c
+++ b/src/install.c
@@ -24,6 +24,7 @@
 #include <pwd.h>
 #include <grp.h>
 #include <selinux/label.h>
+#include <spawn.h>
 #include <sys/wait.h>
 
 #include "system.h"
@@ -32,6 +33,7 @@
 #include "copy.h"
 #include "filenamecat.h"
 #include "full-read.h"
+#include "ignore-value.h"
 #include "mkancesdirs.h"
 #include "mkdir-p.h"
 #include "modechange.h"
@@ -490,33 +492,47 @@ change_timestamps (struct stat const *src_sb, char const *dest,
 static bool
 strip (char const *name)
 {
-  int status;
-  bool ok = false;
-  pid_t pid = fork ();
+  posix_spawnattr_t attr;
+  posix_spawnattr_t *attrp = nullptr;
 
-  switch (pid)
+  /* Try to use vfork for systems where it matters.  */
+  if (posix_spawnattr_init (&attr) == 0)
     {
-    case -1:
-      error (0, errno, _("fork system call failed"));
-      break;
-    case 0:			/* Child. */
-      {
-        char const *safe_name = name;
-        if (name && *name == '-')
-          safe_name = file_name_concat (".", name, nullptr);
-        execlp (strip_program, strip_program, safe_name, nullptr);
-        error (EXIT_FAILURE, errno, _("cannot run %s"),
-               quoteaf (strip_program));
-      }
-    default:			/* Parent. */
-      if (waitpid (pid, &status, 0) < 0)
-        error (0, errno, _("waiting for strip"));
-      else if (! WIFEXITED (status) || WEXITSTATUS (status))
-        error (0, 0, _("strip process terminated abnormally"));
+      if (posix_spawnattr_setflags (&attr, POSIX_SPAWN_USEVFORK) == 0)
+        attrp = &attr;
       else
-        ok = true;      /* strip succeeded */
-      break;
+        ignore_value (posix_spawnattr_destroy (&attr) == 0);
+    }
+
+  /* Construct the arguments to 'strip'.  */
+  char const *safe_name = name;
+  if (name && *name == '-')
+    safe_name = file_name_concat (".", name, nullptr);
+  char const *const argv[] = { strip_program, safe_name, nullptr };
+
+  /* Run 'strip'.  */
+  pid_t pid;
+  int result = posix_spawnp (&pid, strip_program, nullptr, attrp,
+                             (char * const *) argv, environ);
+  if (result != 0)
+    {
+      error (0, result, _("cannot run %s"), quoteaf (strip_program));
+      return false;
     }
+
+  /* Wait for 'strip' to complete and emit a warning message if it fails.  */
+  int status;
+  bool ok = false;
+  if (waitpid (pid, &status, 0) < 0)
+    error (0, errno, _("waiting for strip"));
+  else if (! WIFEXITED (status) || WEXITSTATUS (status))
+    error (0, 0, _("strip process terminated abnormally"));
+  else
+    ok = true;
+
+  if (attrp)
+    ignore_value (posix_spawnattr_destroy (&attr) == 0);
+
   return ok;
 }
 
-- 
2.51.0

Reply via email to