Search code examples
perlwaitpidipcopen3

waitpid and open3 in Perl


If output of the program that is called by open3 is too large (more than 65536) waitpid will run forever.

use IPC::Open3;                                                                  
use POSIX ":sys_wait_h";                                                         

my ($stdin, $stdout, $stderr);                                                   
my $program = "perl -e 'print \"a\" x 65537'";                                   
my $args = [];                                                                   
my $pid = open3 $stdin, $stdout, $stderr, $program, @$args;

waitpid($pid, 0);

The problem is solved by WNOHANG:

my $kid;
while (1) {
    $kid = waitpid( $pid, WNOHANG );
    last unless $kid > 0;
}

But now the return code in $? is -1. It's the return code of waitpid. It can be solved with dirty hack:

my $open3_retcode;
my $kid;
while (1) {
    $open3_retcode = $?;
    $kid = waitpid( $pid, WNOHANG );
    last unless $kid > 0;
}

What is the proper way to do such things?

UPD. It seems that dirty hack is not always works.


Solution

  • If you don't read the output from the program (e.g. $stdout and $stderr) it will hang after a while, because the buffers are full. This will cause it to never return. So the proper way is to read the data the programs sends to you until you get no more data (eof). Then you can call waitpid and it will be successful.