in reply to Re^2: Protection from zombies
in thread Protection from zombies

Change your code, adding this single sequence:
$SIG{CHLD} = sub { my $pid = waitpid(-1, 0); print ">> eof PID $pid -> $?\n"; };
The new result is:
PARENT: PID is 3433 CHILD: PID is 3434, PPID is 3433 >> eof pid 3434 -> 0
Other samples and techniques at perlipc (find REAPER ;)

--
Marco Antonio
Rio-PM

Replies are listed 'Best First'.
Re^4: Protection from zombies
by sgifford (Prior) on May 17, 2005 at 04:05 UTC
    Right. Moving the sleep after the close works too, since the close does a waitpid.
Re^4: Protection from zombies
by nomis80 (Sexton) on May 17, 2005 at 12:40 UTC
    First of all, this seems to not play along very well with my code. For some reason (I do many systems and forks), setting a global SIGCHLD handler makes my program behave very badly in ways I'm not willing to debug. Second, I know I could use the handler locally only in the part I shown in the original post, but I'm wondering why the waitpid done by the close of the pipe does not work. Third, and most interesting, here's a C test I wrote:
    #include <sys/types.h> #include <sys/wait.h> #include <unistd.h> static char buf[512]; int main() { int pfd[2]; pipe( pfd ); pid_t pid = fork(); if ( pid ) { /* parent */ ssize_t s = read( pfd[0], buf, sizeof(buf) ); waitpid( pid, NULL, 0 ); } else { /* child */ dup2( pfd[1], STDOUT_FILENO ); close( STDOUT_FILENO ); } return 0; }
    This is equivalent to the Perl code I wrote in the original post. As strace shows, the parent gets stuck in the read call even if the child closes its stdout. Adding a write of 512 bytes to stdout to the child before it closes it makes the read in the parent return and everything works correctly. But that leaves me with the same question: how can the parent not get stuck in its read if I can't control what the child does?
      I've found how to make my C code right: in the parent and child, I have to close the ends of the pipe that I won't be using. My code becomes:
      #include <sys/types.h> #include <sys/wait.h> #include <unistd.h> static char buf[512]; int main() { int pfd[2]; pipe( pfd ); pid_t pid = fork(); if ( pid ) { /* parent */ close( pfd[1] ); ssize_t s = read( pfd[0], buf, sizeof(buf) ); waitpid( pid, NULL, 0 ); } else { /* child */ close( pfd[0] ); dup2( pfd[1], STDOUT_FILENO ); close( STDOUT_FILENO ); } return 0; }
      This seems to be bulletproof. How can I get that using Perl?
        Perl probably does that for you. I personally don't want to try to find the code that implements the magic open, though.