Re: linux bug in pclose

Michiel Boland (boland@sci.kun.nl)
Sat, 13 Jul 1996 08:42:13 +0200


On versions before 2.0.1, SIGCHLD used to be discarded when a
process calls any of the wait() functions. This is no longer the
case, and is, as far as I can see, correct behaviour.

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