Программист учел проблемы в предыдущей версии функции
exec_and_get_output
(см. историю Что-что вы сказали?).
Он решил все переделать
и воспользоваться функцией open
с тремя аргументами.
Вот новая версия:
# выполняет внешнюю программу,
# возвращает ее stdout в виде массива строк или одной строки в зависимости от контекста вызова.
# Если программу не удалось выполнить или она закончилась ошибкой -- умирает.
sub exec_and_get_output
{
my @cmd = @_;
open( my $FH_OUT, '-|', @cmd ) or die "Can't exec[@cmd]: $? $!";
my @answer = <$FH_OUT>;
if (wantarray) {
chomp for @answer;
return @answer;
} else {
return join '', @answer;
}
}
И что бы вы думали? Теперь функция не умирает в некоторых случаях, когда должна.
Пример кода можно скачать.
И вообще функция не умирает, если внешняя программа запускается, но завершается с ненулевым кодом.
Цитата из perldoc -f open
:
if MODE is "-|", the filename is interpreted as a command that pipes output to us.
... See "Using open() for IPC" in perlipc for more examples of this.
То есть: читайте секцию
“Использование open() для межпроцессного взаимодействия”
в разделе справки perlipc
.
Дело в том, что open
, который используется для запуска
внешней программы, возвращает ложное значение
только в том случае, если внешнюю программу
не удалось запустить.
Напрмер, файл не существует или на нем нет флага исполнимости.
Для того, чтобы получить и проверить код завершения
внешней программы, следует закрыть (close
)
соответствующий файл-хендлер:
open( my $FH_OUT, '-|', @cmd ) or die "Can't exec[@cmd]: $? $!";
my @answer = <$FH_OUT>;
+ close($FH_OUT) or die "Non-zero exit status [@cmd]: $?";
if (wantarray) {
...