From 0c1334eb68de303d9ed40a153bb6793bfdcda77c Mon Sep 17 00:00:00 2001 From: Collin Funk Date: Sun, 19 Oct 2025 15:22:17 -0700 Subject: [PATCH] install: prefer posix_spawnp to fork and execlp * 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 | 2 ++ bootstrap.conf | 4 ++++ src/install.c | 56 +++++++++++++++++++++++++++++++++----------------- 3 files changed, 43 insertions(+), 19 deletions(-) diff --git a/NEWS b/NEWS index 5d70543a16..7641e4f6ac 100644 --- 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. diff --git a/bootstrap.conf b/bootstrap.conf index 5125d66970..523c4923ac 100644 --- a/bootstrap.conf +++ b/bootstrap.conf @@ -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 diff --git a/src/install.c b/src/install.c index 43c7729aff..9cb13d4294 100644 --- a/src/install.c +++ b/src/install.c @@ -24,6 +24,7 @@ #include #include #include +#include #include #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; } -- 2.47.3