timeout assumes that it only has to wait for a single child. But this is not true, it can always inherit other children from its predecessor:
$ sh -c "sleep 1 & exec timeout 2 sh -c 'sleep 3; echo foo'" This will echo foo after three seconds, although the inner shell is supposed to be killed after two seconds. Andreas. >From 331a32b8bbe3cc07d5522004e90fba2bde20a1c3 Mon Sep 17 00:00:00 2001 From: Andreas Schwab <[email protected]> Date: Sat, 16 Jul 2011 13:51:06 +0200 Subject: [PATCH] timeout: ignore inherited children * src/timeout.c (main): Use waitpid instead of wait. --- src/timeout.c | 9 +++++---- 1 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/timeout.c b/src/timeout.c index ef660a7..a5d42f4 100644 --- a/src/timeout.c +++ b/src/timeout.c @@ -358,14 +358,15 @@ main (int argc, char **argv) alarm (timeout); - /* We're just waiting for a single process here, so wait() suffices. - Note the signal() calls above on GNU/Linux and BSD at least, + /* Note the signal() calls above on GNU/Linux and BSD at least, essentially call the lower level sigaction() with the SA_RESTART flag set, which ensures the following wait call will only return if the child exits, not on this process receiving a signal. Also we're not passing WUNTRACED | WCONTINUED to a waitpid() call and so will not get - indication that the child has stopped or continued. */ - if (wait (&status) == -1) + indication that the child has stopped or continued. We may have + inherited children from our predecessor, so a simple wait + doesn't suffice. */ + if (waitpid (monitored_pid, &status, 0) == -1) { /* shouldn't happen. */ error (0, errno, _("error waiting for command")); -- 1.7.6 -- Andreas Schwab, [email protected] GPG Key fingerprint = 58CA 54C7 6D53 942B 1756 01D3 44D5 214B 8276 4ED5 "And now for something completely different."
