2013-08-19 2 views
1

У меня есть команда, которую я выполняю с помощью OPEN с помощью pipe, и я хочу установить тайм-аут в 10 секунд и прервать подпроцесс, если время выполнения превышает это. Однако мой код просто заставляет программу зависать. Почему мой ALARM не доставлен должным образом?Обработчик процесса -SIGALRM не доставлен - Perl

my $pid = 0; 
my $cmd = "someCommand"; 
print "Running Command # $num"; 
eval { 
    local $SIG{ALRM} = sub {      
     print "alarm \n"; 
     kill 9, $pid; 
    };    
    alarm 10; 
    pid = open(my $fh, "$cmd|"); 
    alarm 0; 
}; 
if([email protected]) { 
    die unless [email protected] eq "alarm \n"; 
} else { 
    print $_ while(<$fh>); 
} 

EDIT:

Так Из приведенных ниже ответов, это то, что у меня есть:

my $pid = open(my $fh, qq(perl -e 'alarm 10; exec \@ARGV; die "exec: $!\n" ' $cmd |)); 
print $_ while(<$fh>); 

Но эта печать УСТ.БУДИЛЬНИК на консоль, когда тревоги таймаут ... тогда I dont указать это где-нибудь в коде ... как я могу избавиться от этого, и где бы я поместил пользовательский обработчик событий тревоги?

Спасибо!

ответ

3

Я хочу, чтобы установить таймаут 10 секунд и есть процесс суб отменяется, если время выполнения превышает этот

Другой подход установить сигнализацию на самом подпроцесса, с удобным язык сценариев у вас уже есть:

my $cmd = "someCommand"; 
my $pid = open(my $child_stdout, '-|', 
    'perl', '-e', 'alarm 10; exec @ARGV; die "exec: $!"', $cmd); 
... 

Ваш дочерний процесс первоначально будет Perl (ну, оболочка, а затем Perl), который будет установить сигнализацию на себя, а затем Exec (заменить себя с) $someCommand. Ожидающие сигналы тревоги, однако, составляют inherited across exec()s.

+0

Спасибо за это. Есть ли что-нибудь, что я могу сделать, чтобы сбросить будильник для каждого exec? Как бы я справился с тем, что сигнал тревоги поднят? Как и в, где бы я поместил код обработки? –

+0

Спасибо, @ikegami. Я сопротивлялся этому, потому что я подозреваю, что «someCommand» на самом деле может быть «someCommand --w = = разделенные пробелами аргументы». – pilcrow

+0

@ user6561, аварийный сброс _is_ для каждого exec(). Это уникально для каждого порожденного процесса. Что касается обработки ошибок, вы заметили бы смерть сигнала в '$?' После того, как порожденный процесс завершится. В моей системе это '$? & 127 == 14' (14 - SIGALRM). Подробнее см. В документах для ['system'] (http://perldoc.perl.org/functions/system.html). – pilcrow

2

Весь ваш код выполняет настройку 10 секундного таймаута на вызов open, а не на всю внешнюю программу. Вы хотите привести остальную часть своего взаимодействия с внешней командой в блок eval:

eval { 
    local $SIG{ALRM} = sub {      
     print "alarm \n"; 
     kill 9, $pid; 
    };    
    alarm 10; 
    $pid = open(my $fh, "$cmd|"); 
    print while <$fh>; 
    close $fh; 
    alarm 0; 
}; 
if([email protected]) { 
    die unless [email protected] eq "alarm \n"; 
} 
+0

Это сигнал ALARM CLOCK, но убивает всю программу при сигнале тревоги ... Может, вы знаете, почему это происходит? –

+0

Er, ..., no. Выполняет ли она функцию 'die' в вашем' if ($ @) {...} 'блоке? Каково содержимое '$ @'? – mob

Смежные вопросы