Perl Alarm с подпроцессом - PullRequest
       0

Perl Alarm с подпроцессом

6 голосов
/ 10 декабря 2011

У меня есть Perl-скрипт, который запускает серию пакетных скриптов для регрессионного тестирования.Я хочу реализовать тайм-аут в пакетных сценариях.В настоящее время у меня есть следующий код:

    my $pid = open CMD, "$cmd 2>&1 |";
    eval {
               # setup the alarm
               local $SIG{ALRM} = sub { die "alarm\n" };
               # alarm on the timeout
               alarm $MAX_TIMEOUT;
               log_output("setting alarm to $MAX_TIMEOUT\n");

               # run our exe
               while( <CMD> ) {
                       $$out_ref .= $_;
               }
               $timeRemaining = alarm 0;
            };
            if ($@) {
                    #catch the alarm, kill the executable
            }

Проблема в том, что независимо от того, на какое значение я установил максимальное время ожидания, сигнал тревоги никогда не срабатывает.Я пытался использовать Perl :: Unsafe :: Signals, но это не помогло.

Является ли это наилучшим способом выполнения пакетных сценариев, если я хочу иметь возможность записывать их вывод?Есть ли другой способ сделать то же самое, что позволило бы мне использовать аварийные сигналы, или есть другой метод помимо аварийных сигналов для тайм-аута программы?

Я создал тестовый скрипт, чтобы подтвердить, что аварийный сигнал работает с моимверсия для Perl и Windows, но она не работает, когда я запускаю такую ​​команду.

Я запускаю это с activeperl 5.10.1 на Windows 7 x64.

1 Ответ

4 голосов
/ 10 декабря 2011

Трудно сказать, когда alarm будет работать, когда системный вызов будет и не будет прерван SIGALRM, как один и тот же код может вести себя по-разному в разных операционных системах и т. Д.

Если время вашей работы истекло, вы хотите убить запущенный подпроцесс.Это хороший вариант использования для тревоги бедного человека:

my $pid = open CMD, "$cmd 2>&1 |";
my $time = $MAX_TIMEOUT;

my $poor_mans_alarm = "sleep 1,kill(0,$pid)||exit for 1..$time;kill -9,$pid";
if (fork() == 0) {
    exec($^X, "-e", $poor_mans_alarm);
    die "Poor man's alarm failed to start";  # shouldn't get here
}
# on Windows, instead of  fork+exec, you can say
#    system 1, qq[$^X -e "$poor_mans_alarm"]


...

Сигнализация бедного человека выполняется в отдельном процессе.Каждую секунду он проверяет, активен ли процесс с идентификатором $pid.Если процесс не активен, аварийный процесс завершается.Если процесс все еще остается активным через $time секунд, он посылает сигнал уничтожения процессу (я использовал 9, чтобы сделать его недоступным, и -9, чтобы вынуть все дерево подпроцесса, ваши потребности могут отличаться).

(exec на самом деле может и не понадобиться. Я использую его, потому что я также использую эту идиому для мониторинга процессов, которые могут пережить Perl-скрипт, который их запускал.exec позвоните и скажите

if (fork() == 0) {
    for (1..$time) { sleep 1; kill(0,$pid) || exit }
    kill -9, $pid;
    exit;
}

.)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...