Pádraig Brady <[email protected]> writes: > * src/timeout.c (main): Use PR_SET_PDEATHSIG to ensure the > child is terminated even if the parent terminates abnormally. > * tests/timeout/timeout-group.sh: Add a case to ensure sending > SIGKILL results in the termination of the monitored command. > * NEWS: Mention the improvement. > --- > NEWS | 3 +++ > src/timeout.c | 8 ++++++++ > tests/timeout/timeout-group.sh | 20 +++++++++++++++++++- > 3 files changed, 30 insertions(+), 1 deletion(-) > > diff --git a/NEWS b/NEWS > index 019451d32..3ce4004a8 100644 > --- a/NEWS > +++ b/NEWS > @@ -43,6 +43,9 @@ GNU coreutils NEWS -*- > outline -*- > > csplit, ls, and sort, now handle a more complete set of terminating > signals. > > + 'timeout' on Linux will always terminate the child in the case where the > + timeout process itself dies, like when it receives a KILL signal for > example. > + > ** Build-related > > 'kill' and 'uptime' are no longer built by default. These programs can be > diff --git a/src/timeout.c b/src/timeout.c > index 68ddfd5d6..7634323d4 100644 > --- a/src/timeout.c > +++ b/src/timeout.c > @@ -592,6 +592,14 @@ main (int argc, char **argv) > } > else if (monitored_pid == 0) /* child */ > { > +#if HAVE_PRCTL > + /* Add protection if the parent dies without signalling child. */ > + prctl (PR_SET_PDEATHSIG, term_signal); > +#endif > + /* If we're already reparented to init, don't proceed. */ > + if (getppid () == 1) > + return EXIT_CANCELED; > + > /* Restore signal mask for child. */ > if (sigprocmask (SIG_SETMASK, &orig_set, nullptr) != 0) > { > diff --git a/tests/timeout/timeout-group.sh b/tests/timeout/timeout-group.sh > index 81dadcf9d..ebe299f30 100755 > --- a/tests/timeout/timeout-group.sh > +++ b/tests/timeout/timeout-group.sh > @@ -76,6 +76,13 @@ check_timeout_cmd_running() > { sleep $delay; return 1; } > } > > +check_timeout_cmd_exiting() > +{ > + local delay="$1" > + test -e sig.received || > + { sleep $delay; return 1; } > +} > + > # Terminate any background processes > cleanup_() { kill $pid 2>/dev/null && wait $pid; } > > @@ -88,9 +95,20 @@ retry_delay_ check_timeout_cmd_running .1 6 || fail=1 > kill -USR1 -- -$pid > wait > test -e sig.received || fail=1 > - > rm -f sig.received timeout.running > > +# On Linux ensure we kill the monitored command > +# even if we're terminated abnormally (e.g., get SIGKILL). > +if grep '^#define HAVE_PRCTL 1' "$CONFIG_HEADER" >/dev/null; then > + timeout -sUSR1 25 ./timeout.cmd 20 & pid=$! > + # Wait 6.3s for timeout.cmd to start > + retry_delay_ check_timeout_cmd_running .1 6 || fail=1 > + kill -KILL -- $pid > + wait > + # Wait 6.3s for timeout.cmd to exit > + retry_delay_ check_timeout_cmd_exiting .1 6 || fail=1 > + rm -f sig.received timeout.running > +fi > > # Ensure cascaded timeouts work > # or more generally, ensure we timeout
Patch looks good. It looks like PR_SET_PDEATHSIG was introduced at the same time as prctl, so no need to check that both exist. The man pages say Linux 2.1.57 for both at least (1997). Collin
