summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--NEWS3
-rw-r--r--src/timeout.c17
-rwxr-xr-xtests/misc/timeout-group21
3 files changed, 35 insertions, 6 deletions
diff --git a/NEWS b/NEWS
index a4b11ed41..62262bdd5 100644
--- a/NEWS
+++ b/NEWS
@@ -14,6 +14,9 @@ GNU coreutils NEWS -*- outline -*-
split --number l/... no longer creates extraneous files in certain cases.
[bug introduced in coreutils-8.8]
+ timeout now sends signals to commands that create their own process group.
+ [bug introduced in coreutils-7.0]
+
** Changes in behavior
chmod, chown and chgrp now output the original attributes in messages,
diff --git a/src/timeout.c b/src/timeout.c
index 8f0980b96..ab54ed675 100644
--- a/src/timeout.c
+++ b/src/timeout.c
@@ -104,8 +104,6 @@ cleanup (int sig)
}
if (monitored_pid)
{
- int where = foreground ? monitored_pid : 0;
-
if (sigs_to_ignore[sig])
{
sigs_to_ignore[sig] = 0;
@@ -119,9 +117,20 @@ cleanup (int sig)
kill_after = 0; /* Don't let later signals reset kill alarm. */
}
- send_sig (where, sig);
+ /* Send the signal directly to the monitored child,
+ in case it has itself become group leader,
+ or is not running in a separate group. */
+ send_sig (monitored_pid, sig);
+ /* The normal case is the job has remained in our
+ newly created process group, so send to all processes in that. */
+ if (!foreground)
+ send_sig (0, sig);
if (sig != SIGKILL && sig != SIGCONT)
- send_sig (where, SIGCONT);
+ {
+ send_sig (monitored_pid, SIGCONT);
+ if (!foreground)
+ send_sig (0, SIGCONT);
+ }
}
else /* we're the child or the child is not exec'd yet. */
_exit (128 + sig);
diff --git a/tests/misc/timeout-group b/tests/misc/timeout-group
index 0c3caa0f0..fedd53a60 100755
--- a/tests/misc/timeout-group
+++ b/tests/misc/timeout-group
@@ -34,13 +34,13 @@ cat > timeout.cmd <<\EOF
#!/bin/sh
trap 'touch int.received; exit' INT
touch timeout.running
-sleep 10
+sleep $1
EOF
chmod a+x timeout.cmd
cat > group.sh <<\EOF
#!/bin/sh
-timeout --foreground 5 ./timeout.cmd&
+timeout --foreground 5 ./timeout.cmd 10&
wait
EOF
chmod a+x group.sh
@@ -55,4 +55,21 @@ env kill -INT -- -$!
wait
test -e int.received || fail=1
+rm -f int.received timeout.running
+
+
+# Ensure cascaded timeouts work
+# or more generally, ensure we timeout
+# commands that create their own group
+# This didn't work before 8.13.
+
+# Note the first timeout must send a signal that
+# the second is handling for it to be propagated to the command.
+# SIGINT, SIGTERM, SIGALRM etc. are implicit.
+timeout -sALRM 2 timeout -sINT 10 ./timeout.cmd 5&
+until test -e timeout.running; do sleep .1; done
+kill -ALRM $!
+wait
+test -e int.received || fail=1
+
Exit $fail