wildSmurf has asked for the wisdom of the Perl Monks concerning the following question:

Monks,

I'm seeing IPC::Run spawn a child process which runs as expected, but when the child completes and exits, the parent doesn't notice until the timeout has completely elapsed. The child is listed as a zombi by ps(1). I run this:

$ time perl -MIPC::Run=run,timeout,timer -lwe 'run(["/bin/sleep", 5], +timeout(10));'
and get this:
0m11.129s (0.100u 0.000s)
11 seconds elapsed because the parent didn't cleanup the child process when it finished.

If I simply change the timeout to 3 seconds, I get the expected behavior of IPC::Run throwing an exception.

I've installed IPC::Run v0.80 with the CPAN shell, with a package I built myself and with a Fedora package I downloaded, as well as a Fedora v0.79 package I downloaded, all give the same result.

I've used IPC::Run before without this problem on the same architecture I have now and can't find the culprit.

Host: Linux kolsch.srv.office 2.6.9-55.0.2.EL.xs4.0.1.495xenU #1 SMP Mon Aug 13 09:19:16 EDT 2007 i686 i686 i386 GNU/Linux

OS: CentOS release 4.5 (Final)

Perl: 5.8.5

Replies are listed 'Best First'.
Re: IPC::Run not seeing exit of short child run with long timeout
by pc88mxer (Vicar) on Mar 15, 2008 at 00:10 UTC
    The problem is that you are not having IPC::Run manage any I/O. If you set the timeout to a large value (like 20000), run your program and do an strace on the perl process you'll see that IPC::Run is stuck in the following select call:
    $ strace -p1625 Process 1625 attached - interrupt to quit select(0, NULL, NULL, NULL, {19943, 944000}
    Just change your code so that some pipe between parent and child is closed when your child exits. Then IPC::Run will notice your child's exit. Example:
    use IPC::Run qw(run timeout timer); my $t = timeout(20000); my $out; run(debug => 1, ["/bin/sleep", 5], '>', \$out, $t);
    Update: Another solution is to simply install a CHLD signal handler. It doesn't have to do anything -- the mere fact that the signal is not ignored will cause the select call to be interrupted:
    $SIG{CHLD} = sub {}; run(["/bin/sleep", 5], timeout(20000));
      How wise you are. It works better that way. I was hoping for a more system()-ish output rather than accumulating it all and then dumping it all, but I can make a filter for that, I think.