2003-05-22  Roland McGrath  <roland@redhat.com>

	* defs.h (struct tcb): New member `nzombies'.
	* strace.c (alloctcb): Initialize it.
	(droptcb): Increment our parent's zombie count.
	* process.c (internal_wait): Don't go into TCB_SUSPENDED if the
	process has zombies it can reap.  On the way out, if we reaped
	an untraced process, decrement the zombie count.
diff --git a/process.c b/process.c
index 71b3ca2..0a6f839 100644
--- a/process.c
+++ b/process.c
@@ -1774,7 +1774,17 @@
 		/* ??? WTA: fix bug with hanging children */
 
 		if (!(tcp->u_arg[2] & WNOHANG)) {
-			/* There are traced children */
+			/*
+			 * There are traced children.  We'll make the parent
+			 * block to avoid a false ECHILD error due to our
+			 * ptrace having stolen the children.  However,
+			 * we shouldn't block if there are zombies to reap.
+			 * XXX doesn't handle pgrp matches (u_arg[0]==0,<-1)
+			 */
+			if (tcp->nzombies > 0 &&
+			    (tcp->u_arg[0] == -1 ||
+			     pid2tcb(tcp->u_arg[0]) == NULL))
+				return 0;
 			tcp->flags |= TCB_SUSPENDED;
 			tcp->waitpid = tcp->u_arg[0];
 #ifdef TCB_CLONE_THREAD
@@ -1795,6 +1805,14 @@
 				"internal_wait: should not have resumed %d\n",
 				tcp->pid);
 	}
+	else if (exiting(tcp) && tcp->u_error == 0 && tcp->u_rval > 0 &&
+		 tcp->nzombies > 0 && pid2tcb(tcp->u_rval) == NULL) {
+		/*
+		 * We just reaped a child we don't know about,
+		 * presumably a zombie we already droptcb'd.
+		 */
+		tcp->nzombies--;
+	}
 	return 0;
 }