From dac96ce3e3a2424919fea6a17978b6e91e575d86 Mon Sep 17 00:00:00 2001 From: Collin Funk Date: Sun, 26 Oct 2025 15:33:24 -0700 Subject: [PATCH] timeout: use the more efficient posix_spawn to invoke the command * NEWS: Mention the improvement. Consolidate the posix_spawn improvements into one item. * bootstrap.conf (gnulib_modules): Add posix_spawnattr_setsigmask. * src/timeout.c: Include spawn.h. (main): Setup signals using a posix_spawnattr_t object. Use posix_spawn instead of fork and execvp. --- NEWS | 9 ++------- bootstrap.conf | 1 + src/timeout.c | 42 ++++++++++++++++++++++++------------------ 3 files changed, 27 insertions(+), 25 deletions(-) diff --git a/NEWS b/NEWS index 21106f6910..96b54e108b 100644 --- a/NEWS +++ b/NEWS @@ -51,7 +51,8 @@ GNU coreutils NEWS -*- outline -*- 'fmt', 'nl', and 'pr' will now exit promptly upon receiving a write error, which is significant when reading large / unbounded inputs. - 'install' now uses posix_spawn() to invoke the strip program more efficiently. + install, sort, split, and timeout now use posix_spawn() to invoke child + programs more efficiently and more independently from their own memory usage. 'numfmt': - parses numbers with a non-breaking space character before a unit @@ -59,12 +60,6 @@ GNU coreutils NEWS -*- outline -*- - supports a multi-byte --delimiter character - no longer processes input indefinitely in the presence of write errors - 'sort' now uses posix_spawn() to invoke --compress-program more efficiently - and more independently from sort's memory usage. - - 'split' now uses posix_spawn() to invoke the shell command specified by - --filter more efficiently. - wc -l now operates 10% faster on hosts that support AVX512 instructions. ** Build-related diff --git a/bootstrap.conf b/bootstrap.conf index 4d401d2eb5..6654f61ef4 100644 --- a/bootstrap.conf +++ b/bootstrap.conf @@ -218,6 +218,7 @@ gnulib_modules=" posix_spawnattr_init posix_spawnattr_setflags posix_spawnattr_setsigdefault + posix_spawnattr_setsigmask posix_spawn_file_actions_addclose posix_spawn_file_actions_adddup2 posix_spawn_file_actions_destroy diff --git a/src/timeout.c b/src/timeout.c index cc3b1b0849..15af87c958 100644 --- a/src/timeout.c +++ b/src/timeout.c @@ -49,6 +49,7 @@ #include #include #include +#include #if HAVE_PRCTL # include #endif @@ -547,30 +548,35 @@ main (int argc, char **argv) sigset_t orig_set; block_cleanup_and_chld (term_signal, &orig_set); - monitored_pid = fork (); - if (monitored_pid == -1) + /* posix_spawn doesn't reset SIG_IGN -> SIG_DFL. */ + sigset_t default_set; + sigemptyset (&default_set); + sigaddset (&default_set, SIGTTIN); + sigaddset (&default_set, SIGTTOU); + + int result; + posix_spawnattr_t attr; + + if ((result = posix_spawnattr_init (&attr)) + || (result = posix_spawnattr_setflags (&attr, + (POSIX_SPAWN_USEVFORK + | POSIX_SPAWN_SETSIGDEF + | POSIX_SPAWN_SETSIGMASK))) + || (result = posix_spawnattr_setsigdefault (&attr, &default_set)) + || (result = posix_spawnattr_setsigmask (&attr, &orig_set))) { - error (0, errno, _("fork system call failed")); + error (0, result, _("posix_spawn initialization failed")); return EXIT_CANCELED; } - else if (monitored_pid == 0) /* child */ - { - /* Restore signal mask for child. */ - if (sigprocmask (SIG_SETMASK, &orig_set, nullptr) != 0) - { - error (0, errno, _("child failed to reset signal mask")); - return EXIT_CANCELED; - } - /* exec doesn't reset SIG_IGN -> SIG_DFL. */ - signal (SIGTTIN, SIG_DFL); - signal (SIGTTOU, SIG_DFL); - - execvp (argv[0], argv); + result = posix_spawnp (&monitored_pid, argv[0], nullptr, &attr, argv, + environ); + if (result) + { /* exit like sh, env, nohup, ... */ - int exit_status = errno == ENOENT ? EXIT_ENOENT : EXIT_CANNOT_INVOKE; - error (0, errno, _("failed to run command %s"), quote (command)); + int exit_status = result == ENOENT ? EXIT_ENOENT : EXIT_CANNOT_INVOKE; + error (0, result, _("failed to run command %s"), quote (command)); return exit_status; } else -- 2.47.3