I've tried to use the following (Will wait and waitpid block SIGCHLD and unblock it when they return in Linux?) to answer my question below. The link's resolution leads me to the understanding I have below. Why is it mistaken, then?
Given the following:
The Handler
void sig_child(int sig) { signal(SIGCHLD, sig_child); if (sig == SIGCHLD) { int status; pid_t num; while ((num = waitpid(WAIT_ANY, &status, WNOHANG)) > 0) { } if (num == -1 && errno != ECHILD) { // We shouldn't reach here assert(0); } }
The main blurb:
if (pidnum)
{ //Some work
int status;
pid_t num = waitpid(pidnum, &status, 0);
// Some work
}
I think that the following should take place:
1) The main code (in the second blurb) calls waitpid
2) SIG_CHLD is raised, so control transfers to the signal handler
3) The signal handler removes the terminated child from the signal handler, obtaining its status information
4) When control transfers back to the main code (the second blurb), since the process's child has already been removed from the process table, num should be set to -1
In fact, the following takes place (I'd used some print statements that are now removed to trace the flow), contradicting my understanding above:
1) The main blurb reaches waitpid
2) SIG_CHLD is raised, so control transfers to the handler
3) num is set to -1 and errno to ECHILD
4) Control returns to the main blurb, where num is given the pid of the child that had been forked before.