0

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.

chessman
  • 47
  • 2
  • 6
  • I'd go with `waitpid(-1, WNOHANG);`. That'll reap any children that are 'ready'. If long runnning code, do it periodically. You'll get a few zombies, but they won't persist or do any harm. – Sobrique Jul 14 '14 at 08:55

1 Answers1

4

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.

Steffen Ullrich
  • 114,247
  • 10
  • 131
  • 172
  • You likely want to use IPC::Run instead of open3, so that run itself will take control of the reading/writing loop and ensure you can't forget it. – LeoNerd Jul 14 '14 at 12:46
  • IPC::Open3 is quite low level. I agree with the recommendation to use something higher level. There's IPC::Run and IPC::Run3. – ikegami Jul 14 '14 at 14:49