'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
#include <stdio.h>
#include <sys/types.h>
#include <signal.h>
-#include <spawn.h>
#if HAVE_PRCTL
# include <sys/prctl.h>
#endif
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