Я пишу сценарий Perl, который запишет некоторые исходные данные и отправит те исходные данные во внешнюю программу. Существует маленький, но ненулевой шанс, что эта программа зависнет, и я хочу привести к таймауту ее:
my $pid = fork;
if ($pid > 0){
eval{
local $SIG{ALRM} = sub { die "TIMEOUT!"};
alarm $num_secs_to_timeout;
waitpid($pid, 0);
alarm 0;
};
}
elsif ($pid == 0){
exec('echo blahblah | program_of_interest');
exit(0);
}
Как есть теперь, после $num_secs_to_timeout, program_of_interest все еще сохраняется. Я пытался уничтожить его в анонимной подпрограмме для $SIG{ALRM}
следующим образом:
local $SIG{ALRM} = sub{kill 9, $pid; die "TIMEOUT!"}
но это ничего не делает. program_of_interest все еще сохраняется. Как я иду об уничтожении этого процесса?
Я смог успешно убить свой exec()ed процесс, убив группу процесса , как показано в ответе на вопрос In perl, убивая ребенка и его детей, когда ребенок был создан с помощью open. Я модифицировал свой код следующим образом:
my $pid = fork;
if ($pid > 0){
eval{
local $SIG{ALRM} = sub {kill 9, -$PID; die "TIMEOUT!"};
alarm $num_secs_to_timeout;
waitpid($pid, 0);
alarm 0;
};
}
elsif ($pid == 0){
setpgrp(0,0);
exec('echo blahblah | program_of_interest');
exit(0);
}
После таймаута успешно убивается программа_of_interest.
Хммм ваш код работает для меня , после некоторых незначительных модификаций, которые, как я полагаю, внесены вами, чтобы превратить код в общий пример.
Так что оставляет мне две идеи:
Единственный способ игнорировать SIGKILL - это если процесс застрял в системном вызове, который невозможно прервать. Проверьте состояние зависшего процесса (с помощью ps aux
), если состояние - D, то процесс не может быть остановлен.
Вы также можете проверить, что функция вызывается, выводя что-то из этого.