]> git.ipfire.org Git - thirdparty/coreutils.git/commitdiff
install: prefer posix_spawnp to fork and execlp
authorCollin Funk <collin.funk1@gmail.com>
Sun, 19 Oct 2025 22:22:17 +0000 (15:22 -0700)
committerCollin Funk <collin.funk1@gmail.com>
Wed, 22 Oct 2025 03:26:59 +0000 (20:26 -0700)
* NEWS: Mention the change.
* 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.

NEWS
bootstrap.conf
src/install.c

diff --git a/NEWS b/NEWS
index 5d70543a16d4b786d4919b5e0c6e64ce7af1cf24..7641e4f6ac7680409c079c682664024ab8762660 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -43,6 +43,8 @@ GNU coreutils NEWS                                    -*- outline -*-
 
 ** Improvements
 
+  'install' now uses posix_spawn() to invoke the strip program more efficiently.
+
   numfmt now parses numbers with a non-breaking space character before a unit,
   and parses numbers containing grouping characters from the current locale.
   It also supports a multi-byte --delimiter character.
index 5125d66970b3bc8b85e18c1107e92424b0c2d421..523c4923ac754c397730e097c0ceecb561bfa8f0 100644 (file)
@@ -213,6 +213,10 @@ gnulib_modules="
   pipe-posix
   pipe2
   posix-shell
+  posix_spawnattr_destroy
+  posix_spawnattr_init
+  posix_spawnattr_setflags
+  posix_spawnp
   posixtm
   posixver
   priv-set
index 43c7729affdbe7f224f7493405801a3991e6b3d7..9cb13d42946e531f14311ca656a485162ecc6320 100644 (file)
@@ -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,49 @@ 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 (posix_spawnattr_setflags (&attr, POSIX_SPAWN_USEVFORK) == 0)
+        attrp = &attr;
+      else
+        ignore_value (posix_spawnattr_destroy (&attr));
+    }
+
+  /* Construct the arguments to 'strip'.  */
+  char *concat_name = nullptr;
+  char const *safe_name = name;
+  if (name && *name == '-')
+    safe_name = concat_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);
+
+  bool ok = false;
+  if (result != 0)
+    error (0, result, _("cannot run %s"), quoteaf (strip_program));
+  else
+    {
+      /* Wait for 'strip' to complete, and emit a warning message on failure  */
+      int status;
       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;      /* strip succeeded */
-      break;
+        ok = true;
     }
+
+  free (concat_name);
+  if (attrp)
+    ignore_value (posix_spawnattr_destroy (&attr));
+
   return ok;
 }