waitpid и open3 в Perl

Если вывод программы, вызываемой open3, слишком велик (более 65536), waitpid будет работать вечно.

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);

Проблема решена WNOHANG:

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

Но теперь код возврата в $? это -1. Это код возврата waitpid. Это можно решить с помощью грязного хака:

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

Как правильно делать такие вещи?

UPD. Кажется, что грязный хак не всегда работает.

1 ответ

Решение

Если вы не прочитаете вывод программы (например, $ stdout и $ stderr), он через некоторое время зависнет, потому что буферы заполнены. Это заставит это никогда не возвращаться. Таким образом, правильный способ - читать данные, которые программы посылают вам, пока вы не получите больше данных (eof). Затем вы можете вызвать waitpid, и он будет успешным.

Другие вопросы по тегам