From d0a51c614def6cf4f39fafe8ca7dcef925c4a503 Mon Sep 17 00:00:00 2001 From: =?utf8?q?P=C3=A1draig=20Brady?=
Date: Thu, 20 Nov 2025 16:02:43 +0000
Subject: [PATCH] timeout: handle all terminating signals
* src/timeout.c (term_sig): A new global list of all signals
whose default disposition is to terminate the process.
(install_cleanup): Iterate over the TERM_SIG list, rather than
installing the handler for a specific subset.
(block_cleanup_and_chld): Likewise.
* tests/timeout/timeout.sh: Add a test case for SIGPIPE.
* NEWS: Mention the bug fix.
---
NEWS | 4 +++
src/timeout.c | 66 ++++++++++++++++++++++++++++++++++------
tests/timeout/timeout.sh | 10 +++++-
3 files changed, 69 insertions(+), 11 deletions(-)
diff --git a/NEWS b/NEWS
index b021ed40a5..834c490d15 100644
--- a/NEWS
+++ b/NEWS
@@ -8,6 +8,10 @@ GNU coreutils NEWS -*- outline -*-
This also applies to the sha*sum and b2sum utilities.
[This bug was present in "the beginning".]
+ 'timeout' will now propagate all terminating signals to the monitored command.
+ Previously 'timeout' could have exited and left the monitored command running.
+ [bug introduced with timeout in coreutils-7.0]
+
wc now documents its --debug option, currently used to
indicate the line count acceleration being used.
[bug introduced in coreutils-9.0]
diff --git a/src/timeout.c b/src/timeout.c
index 3443cab4b9..541017cd7e 100644
--- a/src/timeout.c
+++ b/src/timeout.c
@@ -72,6 +72,14 @@
# define SA_RESTART 0
#endif
+#ifndef SIGRTMIN
+# define SIGRTMIN 0
+# undef SIGRTMAX
+#endif
+#ifndef SIGRTMAX
+# define SIGRTMAX (SIGRTMIN - 1)
+#endif
+
#define PROGRAM_NAME "timeout"
#define AUTHORS proper_name_lite ("Padraig Brady", "P\303\241draig Brady")
@@ -191,6 +199,41 @@ chld (MAYBE_UNUSED int sig)
{
}
+static int const term_sig[] =
+ {
+ SIGALRM, /* our timeout. */
+ SIGINT, /* Ctrl-C at terminal for example. */
+ SIGQUIT, /* Ctrl-\ at terminal for example. */
+ SIGHUP, /* terminal closed for example. */
+ SIGTERM, /* if terminated, stop monitored proc. */
+
+ SIGPIPE, SIGUSR1, SIGUSR2,
+ SIGILL, SIGTRAP, SIGABRT, SIGBUS, SIGFPE, SIGSEGV,
+#ifdef SIGXCPU
+ SIGXCPU,
+#endif
+#ifdef SIGXFSZ
+ SIGXFSZ,
+#endif
+#ifdef SIGSYS
+ SIGSYS,
+#endif
+#ifdef SIGVTALRM
+ SIGVTALRM,
+#endif
+#ifdef SIGPROF
+ SIGPROF,
+#endif
+#ifdef SIGPOLL
+ SIGPOLL,
+#endif
+#ifdef SIGPWR
+ SIGPWR,
+#endif
+#ifdef SIGSTKFLT
+ SIGSTKFLT,
+#endif
+ };
static void
cleanup (int sig)
@@ -410,11 +453,13 @@ install_cleanup (int sigterm)
sa.sa_flags = SA_RESTART; /* Restart syscalls if possible, as that's
more likely to work cleanly. */
- sigaction (SIGALRM, &sa, nullptr); /* our timeout. */
- sigaction (SIGINT, &sa, nullptr); /* Ctrl-C at terminal for example. */
- sigaction (SIGQUIT, &sa, nullptr); /* Ctrl-\ at terminal for example. */
- sigaction (SIGHUP, &sa, nullptr); /* terminal closed for example. */
- sigaction (SIGTERM, &sa, nullptr); /* if killed, stop monitored proc. */
+ for (int i = 0; i < countof (term_sig); i++)
+ sigaction (term_sig[i], &sa, nullptr);
+
+ /* Real Time signals also terminate by default. */
+ for (int s = SIGRTMIN; s <= SIGRTMAX; s++)
+ sigaction (s, &sa, nullptr);
+
sigaction (sigterm, &sa, nullptr); /* user specified termination signal. */
}
@@ -429,11 +474,12 @@ block_cleanup_and_chld (int sigterm, sigset_t *old_set)
sigset_t block_set;
sigemptyset (&block_set);
- sigaddset (&block_set, SIGALRM);
- sigaddset (&block_set, SIGINT);
- sigaddset (&block_set, SIGQUIT);
- sigaddset (&block_set, SIGHUP);
- sigaddset (&block_set, SIGTERM);
+ for (int i = 0; i < countof (term_sig); i++)
+ sigaddset (&block_set, term_sig[i]);
+
+ for (int s = SIGRTMIN; s <= SIGRTMAX; s++)
+ sigaddset (&block_set, s);
+
sigaddset (&block_set, sigterm);
sigaddset (&block_set, SIGCHLD);
diff --git a/tests/timeout/timeout.sh b/tests/timeout/timeout.sh
index e3defdd4e2..d799cbfd96 100755
--- a/tests/timeout/timeout.sh
+++ b/tests/timeout/timeout.sh
@@ -17,7 +17,7 @@
# along with this program. If not, see