Just as the title says, one process forks waits for its child to receive a SIGSTOP (self sent by the child) but it does not wake up after as if it didn't receive any SIGCHLD (but it actually did, tested with strace).
Anyone any ideas?
int main() {
if (fork()) {
wait(NULL);
write(1, "Bye\n", 4);
} else {
kill(getpid(), SIGSTOP);
write(1, "Hello\n", 6);
}
return 0;
}
They both hang, whereas only the child should.
The specification for wait
says that it reports only children that have exited, not children that have stopped. You should use
waitpid(-1, 0, WUNTRACED);
instead.
The flag name WUNTRACED
is a little cryptic - why isn't it WSTOPPED
? This is a point where the standardized wait*
API brushes up against the not-standardized ptrace
API. Compare POSIX's definition of WUNTRACED
…
- WUNTRACED
- The status of any child processes specified by pid that are stopped, and whose status has not yet been reported since they stopped, shall also be reported to the requesting process.
… with its documentation in the Linux manpage …
- WUNTRACED
- also return if a child has stopped (but not traced via ptrace(2)). Status for traced children which have stopped is provided even if this option is not specified.
So basically the default behavior of wait*
has a special case embedded in it for the convenience of people writing debuggers (people writing debuggers will take every convenience they can get) and that special case has been around for so long that it affected the names chosen for waitpid
's flags. (I don't know one way or the other, but I would not be surprised to learn that ptrace
stops are older than job control stops.)