On 4/9/07, Brian Candler <[EMAIL PROTECTED]> wrote:
...
Suppose child 1 dies, causing a SIGCHLD to be pending, and then a second
child dies, before sigsuspend() unblocks the signal. sigsuspend returns, and
one child is reaped. Next time around the loop, will the second child be
reaped? If so, why?

Hmm, nice catch.

In theory, sigsuspend() should wake up immediately the second time
through, as SIGCHLD should be pending as long as there's a child in
the exited-but-not-yet-reaped state.  That is, the first waitpid()
shouldn't cancel the pending state because there's another child
process ready to be reaped.  To quote the SUS pages:
http://www.opengroup.org/onlinepubs/009695399/functions/waitpid.html
       Otherwise, if SIGCHLD is blocked, if wait() or waitpid()
return because the status
       of a child process is available, any pending SIGCHLD signal
shall be cleared
       unless the status of another child process is available.

Note that last line.

However, OpenBSD 4.0 doesn't actually comply with that: after
waitpid() there will be no SIGCHLD pending, even if there are
additional children to reap.

So, if you're going to have multiple children, you need to call
waitpid(-1, &ret, WNOHANG) until it returns zero or -1/ECHILD before
you loop back to sigsuspend() again.  That way you can be sure that
you haven't lost any SIGCHLDs before you reenter the sigsuspend().
I've actually confirmed that that loop does work as expected, unlike
the original example which only works with one child.


Philip Guenther

Reply via email to