Убить зависшего ребенка
Мой Perl-скрипт запускает внешнюю программу (которая принимает один параметр командной строки) и обрабатывает ее вывод. Первоначально я делал это:
my @result = `prog arg`;
Однако оказывается, что программа глючит и в редких случаях зависает непредсказуемо. Как я могу убить программу, если она не вышла через определенное время? Сценарий должен работать как в Windows, так и в Linux, и, насколько я понимаю, аварийные сигналы и вилки не работают (или вообще не работают) в Windows.
Я нашел модуль под названиемIPC :: Run но я не могу понять, как правильно использовать его из документации. :-( Я попробовал это:
use strict;
use warnings;
use IPC::Run qw(run timeout);
my $in;
my $out;
my $err;
my @result;
my @cmd = qw(prog arg);
run \@cmd, \$in, \$out, \$err, timeout (10) or die "@cmd: $?";
push @result, $_ while (<$out>);
close $out;
print @result;
В качестве теста я создал программу, которая просто спит 60 секунд, печатает строку вstdout
и выходит. Когда я пытаюсь запустить его с вышеуказанным кодом, он зависает на 60 секунд (вместо 10 секунд, как указано в тайм-ауте) и прерывается с причудливой ошибкой:
IPC::Run: timeout on timer #1 at C:/Bin/Unix/Perl/site/lib/IPC/Run.pm line 2956
Затем я нашел другой модуль,Proc :: Расписание, Из описания, похоже, делаю именно то, что хочу. За исключением того, что это не работает! Я попробовал это:
use strict;
use warnings;
use Proc::Reliable;
my $proc = Proc::Reliable->new ();
$proc->maxtime (10);
my $out = $proc->run ("prog arg");
print "$out\n";
Это действительно прерывает дочерний процесс через 10 секунд. Все идет нормально. Но затем я изменил внешнюю программу и заставил ее спать только 5 секунд. Это означает, что программа должна завершиться до 10-секундного тайм-аута, указанного в приведенном выше коде и егоstdout
вывод должен быть записан в переменную$out
, Но это не так! Приведенный выше скрипт ничего не выводит.
Есть идеи как правильно это сделать? (Исправление глючной внешней программы не вариант.) Заранее спасибо.