The branch stable/14 has been updated by kib:

URL: 
https://cgit.FreeBSD.org/src/commit/?id=795153bda6dae27ceac4a7298106c00ca706b0ec

commit 795153bda6dae27ceac4a7298106c00ca706b0ec
Author:     Aaron LI <a...@aaronly.me>
AuthorDate: 2025-04-03 01:20:01 +0000
Commit:     Konstantin Belousov <k...@freebsd.org>
CommitDate: 2025-06-16 08:51:53 +0000

    timeout(1): Catch all signals and propagate them
    
    (cherry picked from commit 844cef26e810d903e11bf83cc6f6fd2e22a299f1)
---
 bin/timeout/timeout.1 | 22 ++++++++++++
 bin/timeout/timeout.c | 92 +++++++++++++++++++++++++++++++--------------------
 2 files changed, 79 insertions(+), 35 deletions(-)

diff --git a/bin/timeout/timeout.1 b/bin/timeout/timeout.1
index 371a167d19f3..44525daaec59 100644
--- a/bin/timeout/timeout.1
+++ b/bin/timeout/timeout.1
@@ -73,6 +73,28 @@ inherited, except for the signal that will be sent upon 
timeout,
 which is reset to take the default action and should terminate
 the process.
 .Pp
+If
+.Nm
+receives the
+.Dv SIGALRM
+signal, it will behave as if the time limit has been reached
+and send the specified signal to
+.Ar command .
+For any other signals delivered to
+.Nm ,
+it will propagate them to
+.Ar command ,
+with the exception of
+.Dv SIGKILL
+and
+.Dv SIGSTOP .
+If you want to prevent the
+.Ar command
+from being timed out, send
+.Dv SIGKILL
+to
+.Nm .
+.Pp
 The options are as follows:
 .Bl -tag -width indent
 .It Fl f , Fl -foreground
diff --git a/bin/timeout/timeout.c b/bin/timeout/timeout.c
index 1c4cfa6e017d..6e93e9e2911c 100644
--- a/bin/timeout/timeout.c
+++ b/bin/timeout/timeout.c
@@ -1,6 +1,7 @@
 /*-
  * Copyright (c) 2014 Baptiste Daroussin <b...@freebsd.org>
  * Copyright (c) 2014 Vsevolod Stakhov <vsevo...@freebsd.org>
+ * Copyright (c) 2025 Aaron LI <a...@aaronly.me>
  * All rights reserved.
  *
  * Redistribution and use in source and binary forms, with or without
@@ -47,8 +48,10 @@
 #define EXIT_CMD_NOENT 127
 
 static volatile sig_atomic_t sig_chld = 0;
-static volatile sig_atomic_t sig_term = 0;
 static volatile sig_atomic_t sig_alrm = 0;
+static volatile sig_atomic_t sig_term = 0; /* signal to terminate children */
+static volatile sig_atomic_t sig_other = 0; /* signal to propagate */
+static int killsig = SIGTERM; /* signal to kill children */
 static const char *command = NULL;
 static bool verbose = false;
 
@@ -137,19 +140,46 @@ parse_signal(const char *str)
 static void
 sig_handler(int signo)
 {
-       switch (signo) {
-       case SIGINT:
-       case SIGHUP:
-       case SIGQUIT:
-       case SIGTERM:
+       if (signo == killsig) {
                sig_term = signo;
-               break;
+               return;
+       }
+
+       switch (signo) {
        case SIGCHLD:
                sig_chld = 1;
                break;
        case SIGALRM:
                sig_alrm = 1;
                break;
+       case SIGHUP:
+       case SIGINT:
+       case SIGQUIT:
+       case SIGILL:
+       case SIGTRAP:
+       case SIGABRT:
+       case SIGEMT:
+       case SIGFPE:
+       case SIGBUS:
+       case SIGSEGV:
+       case SIGSYS:
+       case SIGPIPE:
+       case SIGTERM:
+       case SIGXCPU:
+       case SIGXFSZ:
+       case SIGVTALRM:
+       case SIGPROF:
+       case SIGUSR1:
+       case SIGUSR2:
+               /*
+                * Signals with default action to terminate the process.
+                * See the sigaction(2) man page.
+                */
+               sig_term = signo;
+               break;
+       default:
+               sig_other = signo;
+               break;
        }
 }
 
@@ -214,8 +244,6 @@ main(int argc, char **argv)
 {
        int ch, status, sig;
        int pstat = 0;
-       int killsig = SIGTERM;
-       size_t i;
        pid_t pid, cpid;
        double first_kill;
        double second_kill = 0;
@@ -225,17 +253,8 @@ main(int argc, char **argv)
        bool do_second_kill = false;
        bool child_done = false;
        sigset_t zeromask, allmask, oldmask;
-       struct sigaction signals;
+       struct sigaction sa;
        struct procctl_reaper_status info;
-       int signums[] = {
-               -1,
-               SIGTERM,
-               SIGINT,
-               SIGHUP,
-               SIGCHLD,
-               SIGALRM,
-               SIGQUIT,
-       };
 
        const char optstr[] = "+fhk:ps:v";
        const struct option longopts[] = {
@@ -316,22 +335,17 @@ main(int argc, char **argv)
 
        /* parent continues here */
 
-       memset(&signals, 0, sizeof(signals));
-       sigemptyset(&signals.sa_mask);
-
-       if (killsig != SIGKILL && killsig != SIGSTOP)
-               signums[0] = killsig;
-
-       for (i = 0; i < sizeof(signums) / sizeof(signums[0]); i++)
-               sigaddset(&signals.sa_mask, signums[i]);
-
-       signals.sa_handler = sig_handler;
-       signals.sa_flags = SA_RESTART;
-
-       for (i = 0; i < sizeof(signums) / sizeof(signums[0]); i++) {
-               if (signums[i] > 0 &&
-                   sigaction(signums[i], &signals, NULL) == -1)
-                       err(EXIT_FAILURE, "sigaction()");
+       /* Catch all signals in order to propagate them. */
+       memset(&sa, 0, sizeof(sa));
+       sigfillset(&sa.sa_mask);
+       sa.sa_handler = sig_handler;
+       sa.sa_flags = SA_RESTART;
+       for (sig = 1; sig < sys_nsig; sig++) {
+               if (sig == SIGKILL || sig == SIGSTOP || sig == SIGCONT ||
+                   sig == SIGTTIN || sig == SIGTTOU)
+                       continue;
+               if (sigaction(sig, &sa, NULL) == -1)
+                       err(EXIT_FAILURE, "sigaction(%d)", sig);
        }
 
        /* Don't stop if background child needs TTY */
@@ -399,6 +413,14 @@ main(int argc, char **argv)
                                do_second_kill = false;
                                killsig = SIGKILL;
                        }
+
+               } else if (sig_other) {
+                       /* Propagate any other signals. */
+                       sig = sig_other;
+                       sig_other = 0;
+                       logv("received signal %s(%d)", sys_signame[sig], sig);
+
+                       send_sig(pid, sig, foreground);
                }
        }
 

Reply via email to