У меня есть цикл perl IO :: Select для запуска команды (без stdin) и сохранения ее вывода в различные журналы.
Это прекрасно работало в течение ряда лет, но внезапно оно плохо себя ведетс одной конкретной командой.Команда выполняется до конца и правильно завершается, если она запускается из командной строки, но когда я запускаю ее из этого кода Perl, то после того, как это сделано (как видно из журналов), дочерний процесс не завершится, и он просто будет находиться взависшее состояние.У меня нет прав доступа к системам, на которых это происходит, поэтому я не вижу точно, что застряло.
Код по сути:
# Start process
open(local *nostdin, '<', '/dev/null') or die $!;
my $pid = open3('<&nostdin',
my $outH = gensym(),
my $errH = gensym(),
$command
);
# Setup select
my $sel = IO::Select->new();
$sel->add($outH);
$sel->add($errH);
# Select loop
while (my @ready = $sel->can_read()) {
foreach my $handle (@ready) {
my $bytesRead = sysread($handle, my $buf='', 1024);
if ($bytesRead <= 0) {
warn("Error reading command out $!\n Command: $command\n") if $bytesRead;
$sel->remove($handle);
next;
}
if ($handle==$outH) {
syswrite(SYSOUT,$buf) if $stdoutOpen;
syswrite(SYSLOG,$buf) if $logOpen;
}
if ($handle==$errH) {
syswrite(SYSERR,$buf) if $stderrOpen;
syswrite(SYSLOG,$buf) if $logOpen;
}
}
}
Есть ли что-нибудь, что яможет быть не так?И даже если есть ошибка, как цикл ввода-вывода perl может удерживать дочерний процесс от его выхода?Кажется, что когда ребенок выходит, он закрывает все свои операции ввода-вывода, и мы заканчиваем этот цикл (как всегда было с этим кодом).
Я провел несколько тестов с использованием waitPidи некоторый вывод, и похоже, что $ outH закрывается, но $ errH никогда не имеет никаких данных и никогда не закрывается, и тогда я вижу из waitPid, что дочерний процесс имеет выход.
Итак, я открываю два канала,для ребенка и ребенка ошибаться.Дочерний объект использует выходной канал, а не канал ошибок.Затем дочерний элемент закрывает выходной канал и выходит, каким-то образом этот выход не закрывает канал ошибок.Как это происходит?Это что-то, что ребенок мог даже сделать нарочно?