In past-2.0.0 kernels SIGCHLD is never lost. That means that it
is still delivered when one calls system(), popen/pclose.
Ergo: you have to be a bit more careful inside the
signal handler and do proper error checking and stuff.
In pre-2.0.1, this is what happens with your program:
fork() creates the first child
popen() creates the second child
pclose() waits for the second child to exit; SIGCHLD gets discarded,
the handler is not called.
When the first child exits, the signal handler is called; nbpgm
is decreased, and the program exits.
In post-2.0.1, we now have this behaviour:
fork() creates the first child
popen() creates the second child
pclose() waits for second child; SIGCHLD is not discarded,
handler is called, nbpgm is mistakenly decreased, program exits.
The first child keeps running, but will now also get a SIGCHLD
when the system() finishes. But since system() has already
waited for *its* child process, wait() now returns -1. This
explains the mysterious `pid -1'.
So, to fix your program, you should check inside the SIGCHLD
handler *what* child has exited, and realize that wait() may
return -1 when someone else already waited for the child.
Hope this has made matters clearer.
-- Michiel Boland <boland@sci.kun.nl> University of Nijmegen The Netherlands