diff options
| author | Aaron LI <aly@aaronly.me> | 2025-04-03 02:51:06 +0000 |
|---|---|---|
| committer | Konstantin Belousov <kib@FreeBSD.org> | 2025-06-16 08:51:53 +0000 |
| commit | de24ba56a663c608edf8091900a49b48d088896c (patch) | |
| tree | b816cb7ed15be71dbc868321de5db0e3c878dc9d /bin/timeout/timeout.c | |
| parent | 795153bda6dae27ceac4a7298106c00ca706b0ec (diff) | |
Diffstat (limited to 'bin/timeout/timeout.c')
| -rw-r--r-- | bin/timeout/timeout.c | 35 |
1 files changed, 33 insertions, 2 deletions
diff --git a/bin/timeout/timeout.c b/bin/timeout/timeout.c index 6e93e9e2911c..e9c4e22fc7d3 100644 --- a/bin/timeout/timeout.c +++ b/bin/timeout/timeout.c @@ -28,6 +28,7 @@ #include <sys/cdefs.h> #include <sys/procctl.h> +#include <sys/resource.h> #include <sys/time.h> #include <sys/wait.h> @@ -239,6 +240,34 @@ set_interval(double iv) err(EXIT_FAILURE, "setitimer()"); } +/* + * In order to avoid any possible ambiguity that a shell may not set '$?' to + * '128+signal_number', POSIX.1-2024 requires that timeout mimic the wait + * status of the child process by terminating itself with the same signal, + * while disabling core generation. + */ +static void __dead2 +kill_self(int signo) +{ + sigset_t mask; + struct rlimit rl; + + /* Reset the signal disposition and make sure it's unblocked. */ + signal(signo, SIG_DFL); + sigfillset(&mask); + sigdelset(&mask, signo); + sigprocmask(SIG_SETMASK, &mask, NULL); + + /* Disable core generation. */ + memset(&rl, 0, sizeof(rl)); + setrlimit(RLIMIT_CORE, &rl); + + logv("killing self with signal %s(%d)", sys_signame[signo], signo); + kill(getpid(), signo); + err(128 + signo, "signal %s(%d) failed to kill self", + sys_signame[signo], signo); +} + int main(int argc, char **argv) { @@ -430,10 +459,12 @@ main(int argc, char **argv) if (timedout && !preserve) { pstat = EXIT_TIMEOUT; } else { + if (WIFSIGNALED(pstat)) + kill_self(WTERMSIG(pstat)); + /* NOTREACHED */ + if (WIFEXITED(pstat)) pstat = WEXITSTATUS(pstat); - else if (WIFSIGNALED(pstat)) - pstat = 128 + WTERMSIG(pstat); } return (pstat); |
