git: de24ba56a663 - stable/14 - timeout(1): Kill self with the same signal that terminated the child
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Mon, 16 Jun 2025 08:54:08 UTC
The branch stable/14 has been updated by kib:
URL: https://cgit.FreeBSD.org/src/commit/?id=de24ba56a663c608edf8091900a49b48d088896c
commit de24ba56a663c608edf8091900a49b48d088896c
Author: Aaron LI <aly@aaronly.me>
AuthorDate: 2025-04-03 02:51:06 +0000
Commit: Konstantin Belousov <kib@FreeBSD.org>
CommitDate: 2025-06-16 08:51:53 +0000
timeout(1): Kill self with the same signal that terminated the child
(cherry picked from commit 613310263ae1f0f65df498dc8e98f460b781946d)
---
bin/timeout/timeout.1 | 51 ++++++++++++++++++++++++---------------------------
bin/timeout/timeout.c | 35 +++++++++++++++++++++++++++++++++--
2 files changed, 57 insertions(+), 29 deletions(-)
diff --git a/bin/timeout/timeout.1 b/bin/timeout/timeout.1
index 44525daaec59..43a484dac76f 100644
--- a/bin/timeout/timeout.1
+++ b/bin/timeout/timeout.1
@@ -146,37 +146,33 @@ hours
days
.El
.Sh EXIT STATUS
-If the timeout was not reached, the exit status of
-.Ar command
-is returned.
-.Pp
-If the timeout was reached and
-.Fl -preserve-status
-is set, the exit status of
-.Ar command
-is returned.
-If
+If the time limit was reached and the
.Fl -preserve-status
-is not set, an exit status of 124 is returned.
-.Pp
-If an invalid parameter is passed to
-.Fl s
-or
-.Fl k ,
-the exit status returned is 125.
-.Pp
-If
+option is not specified, the exit status is 124.
+Otherwise,
+.Nm
+exits with the same exit status as the
+.Ar command .
+For example,
+.Nm
+will terminate itself with the same signal if the
.Ar command
-is an otherwise invalid program, the exit status returned is 126.
+is terminated by a signal.
.Pp
-If
+If an error occurred, the following exit values are returned:
+.Bl -tag -offset indent with indent -compact
+.It 125
+An error other than the two described below occurred.
+For example, an invalid duration or signal was specified.
+.It 126
+The
.Ar command
-refers to a non-existing program, the exit status returned is 127.
-.Pp
-If
+was found but could not be executed.
+.It 127
+The
.Ar command
-exits after receiving a signal, the exit status returned is the signal number
-plus 128.
+could not be found.
+.El
.Sh EXAMPLES
Run
.Xr sleep 1
@@ -202,7 +198,8 @@ $ echo $?
.Pp
Same as above but preserving status.
The exit status is 128 + signal number (15 for
-.Dv SIGTERM ) :
+.Dv SIGTERM )
+for most shells:
.Bd -literal -offset indent
$ timeout --preserve-status 2 sleep 4
$ echo $?
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);