流程挂起-SIGALRM未交付 - Perl

时间:2013-08-19 16:53:49

标签: perl

我有一个命令,我正在使用带管道的OPEN执行,我想设置10秒的超时,并且如果执行时间超过此值,则子进程中止。但是,我的代码只是导致程序挂起 - 为什么我的ALARM没有正确交付?

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($@) {
    die unless $@ eq "alarm \n";
} else {
    print $_ while(<$fh>);
}

编辑:

所以从下面的答案中,这就是我所拥有的:

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

但是当警报超时时,这会向控制台打印ALARM CLOCK ...而我在代码中的任何地方都没有指定...我怎么能摆脱这个,我会把自定义警报事件处理程序放在哪里?

谢谢!

2 个答案:

答案 0 :(得分:3)

  

我想将超时设置为10秒,并且如果执行时间超过此,则子流程将中止

另一种方法是使用您已有的方便脚本语言在子进程本身上设置警报:

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

你的子进程最初将是perl(好吧,shell,然后是perl),它会自动设置一个警报,然后执行exec(替换为$someCommand。但是,待处理的警报为inherited across exec()s

答案 1 :(得分:2)

您的所有代码都在open来电设置10秒超时,而不是整个外部程序。您希望将剩余的与外部命令的交互带入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($@) {
    die unless $@ eq "alarm \n";
}