Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 15 Feb 2015 20:10:54 +0000 (UTC)
From:      Ed Maste <emaste@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r278810 - head/usr.bin/timeout
Message-ID:  <201502152010.t1FKAspg028440@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: emaste
Date: Sun Feb 15 20:10:53 2015
New Revision: 278810
URL: https://svnweb.freebsd.org/changeset/base/278810

Log:
  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

Modified:
  head/usr.bin/timeout/timeout.c

Modified: head/usr.bin/timeout/timeout.c
==============================================================================
--- head/usr.bin/timeout/timeout.c	Sun Feb 15 20:03:42 2015	(r278809)
+++ head/usr.bin/timeout/timeout.c	Sun Feb 15 20:10:53 2015	(r278810)
@@ -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()");
 	}



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201502152010.t1FKAspg028440>