summaryrefslogtreecommitdiffstats
path: root/usr.bin/timeout
diff options
context:
space:
mode:
authoremaste <emaste@FreeBSD.org>2015-02-15 20:10:53 +0000
committeremaste <emaste@FreeBSD.org>2015-02-15 20:10:53 +0000
commitcf55e52764b13492f0b203428c9c154500267d52 (patch)
tree41bf90082999db215a9c96369225410ce090b5a5 /usr.bin/timeout
parent90e8bc75a3dd74ca3057c4ad783aca20420937e0 (diff)
downloadFreeBSD-src-cf55e52764b13492f0b203428c9c154500267d52.zip
FreeBSD-src-cf55e52764b13492f0b203428c9c154500267d52.tar.gz
timeout: handle zombie grandchildren
timeout previously collected only one child status with wait(2). If this was one of the grandchildren timeout would return to sigsuspend and wait until the timeout expired. Instead, loop for all children. PR: kern/197608 Reviewed by: bapt, kib MFC after: 1 week Sponsored by: The FreeBSD Foundation
Diffstat (limited to 'usr.bin/timeout')
-rw-r--r--usr.bin/timeout/timeout.c32
1 files changed, 19 insertions, 13 deletions
diff --git a/usr.bin/timeout/timeout.c b/usr.bin/timeout/timeout.c
index 06dc086..a682dde 100644
--- a/usr.bin/timeout/timeout.c
+++ b/usr.bin/timeout/timeout.c
@@ -172,6 +172,7 @@ main(int argc, char **argv)
double second_kill;
bool timedout = false;
bool do_second_kill = false;
+ bool child_done = false;
struct sigaction signals;
struct procctl_reaper_status info;
struct procctl_reaper_kill killemall;
@@ -187,7 +188,6 @@ main(int argc, char **argv)
foreground = preserve = 0;
second_kill = 0;
- cpid = -1;
const struct option longopts[] = {
{ "preserve-status", no_argument, &preserve, 1 },
@@ -281,20 +281,26 @@ main(int argc, char **argv)
if (sig_chld) {
sig_chld = 0;
- while (((cpid = wait(&status)) < 0) && errno == EINTR)
- continue;
- if (cpid == pid) {
- pstat = status;
- if (!foreground)
- break;
+ while ((cpid = waitpid(-1, &status, WNOHANG)) != 0) {
+ if (cpid < 0) {
+ if (errno == EINTR)
+ continue;
+ else
+ break;
+ } else if (cpid == pid) {
+ pstat = status;
+ child_done = true;
+ }
}
- if (!foreground) {
- procctl(P_PID, getpid(), PROC_REAP_STATUS,
- &info);
- if (info.rs_children == 0) {
- cpid = pid;
+ if (child_done) {
+ if (foreground) {
break;
+ } else {
+ procctl(P_PID, getpid(),
+ PROC_REAP_STATUS, &info);
+ if (info.rs_children == 0)
+ break;
}
}
} else if (sig_alrm) {
@@ -336,7 +342,7 @@ main(int argc, char **argv)
}
}
- while (cpid != pid && wait(&pstat) == -1) {
+ while (!child_done && wait(&pstat) == -1) {
if (errno != EINTR)
err(EX_OSERR, "waitpid()");
}
OpenPOWER on IntegriCloud