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
