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;
}