* NEWS: Mention the improvement.
* 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 | 3 +++
bootstrap.conf | 1 +
src/timeout.c | 42 ++++++++++++++++++++++++------------------
3 files changed, 28 insertions(+), 18 deletions(-)
diff --git a/NEWS b/NEWS
index 402585be3..9ebedb3a1 100644
--- a/NEWS
+++ b/NEWS
@@ -65,6 +65,9 @@ GNU coreutils NEWS -*-
outline -*-
'split' now uses posix_spawn() to invoke the shell command specified by
--filter more efficiently.
+ 'timeout' now uses posix_spawn() to invoke the specified command more
+ efficiently.
+
wc -l now operates 10% faster on hosts that support AVX512 instructions.
diff --git a/bootstrap.conf b/bootstrap.conf
index 4d401d2eb..6654f61ef 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 cc3b1b084..15af87c95 100644
--- a/src/timeout.c
+++ b/src/timeout.c
@@ -49,6 +49,7 @@
#include <stdio.h>
#include <sys/types.h>
#include <signal.h>
+#include <spawn.h>
#if HAVE_PRCTL
# include <sys/prctl.h>
#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.51.0