]> git.ipfire.org Git - thirdparty/coreutils.git/commitdiff
timeout: use fork and execvp instead of posix_spawn
authorCollin Funk <collin.funk1@gmail.com>
Fri, 31 Oct 2025 04:10:52 +0000 (21:10 -0700)
committerCollin Funk <collin.funk1@gmail.com>
Sat, 1 Nov 2025 02:57:36 +0000 (19:57 -0700)
* NEWS: Remove timeout from the list of programs that use posix_spawn.
* bootstrap.conf (gnulib_modules): Remove posix_spawnattr_setsigmask.
* src/timeout.c: Don't include spawn.h.
(main): Use fork and execvp instead of posix_spawn.

This reverts commit dac96ce3e3a2424919fea6a17978b6e91e575d86.

NEWS
bootstrap.conf
src/timeout.c

diff --git a/NEWS b/NEWS
index 7a21ffce3b95151b46bfcfef64c478ffb867cb03..ee0213fb787b3303751c2f5f999a82ff63d4241a 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -56,8 +56,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, sort, split, and timeout now use posix_spawn() to invoke child
-  programs more efficiently and more independently from their own memory usage.
+  install, sort, and split 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
index 3a5a4cfa815d9fdbef097fd84b941e3071c14b69..ec68ac8bfe5632cfb6177b9f39a7a6b15da67f7f 100644 (file)
@@ -219,7 +219,6 @@ 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
index 15af87c95884c31f69243ca9b950379a89164635..3443cab4b9642302e5b154907bb4b71348a07736 100644 (file)
@@ -49,7 +49,6 @@
 #include <stdio.h>
 #include <sys/types.h>
 #include <signal.h>
-#include <spawn.h>
 #if HAVE_PRCTL
 # include <sys/prctl.h>
 #endif
@@ -548,35 +547,35 @@ main (int argc, char **argv)
   sigset_t orig_set;
   block_cleanup_and_chld (term_signal, &orig_set);
 
-  /* 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)))
+  /* We cannot use posix_spawn here since the child will have an exit status of
+     127 for any failure.  If implemented through fork and exec, posix_spawn
+     will return successfully and 'timeout' will have no way to determine if it
+     should exit with EXIT_CANNOT_INVOKE or EXIT_ENOENT upon checking the exit
+     status of the child.  */
+  monitored_pid = fork ();
+  if (monitored_pid == -1)
     {
-      error (0, result, _("posix_spawn initialization failed"));
+      error (0, errno, _("fork system call 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;
+        }
 
-  result = posix_spawnp (&monitored_pid, argv[0], nullptr, &attr, argv,
-                         environ);
+      /* exec doesn't reset SIG_IGN -> SIG_DFL.  */
+      signal (SIGTTIN, SIG_DFL);
+      signal (SIGTTOU, SIG_DFL);
+
+      execvp (argv[0], argv);
 
-  if (result)
-    {
       /* exit like sh, env, nohup, ...  */
-      int exit_status = result == ENOENT ? EXIT_ENOENT : EXIT_CANNOT_INVOKE;
-      error (0, result, _("failed to run command %s"), quote (command));
+      int exit_status = errno == ENOENT ? EXIT_ENOENT : EXIT_CANNOT_INVOKE;
+      error (0, errno, _("failed to run command %s"), quote (command));
       return exit_status;
     }
   else