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, и он будет успешным.