进程挂起-未交付SIGALRM-Perl



我有一个命令,我正在使用带管道的OPEN执行,我想设置10秒的超时,如果执行时间超过这个时间,则中止子进程。然而,我的代码只是导致程序挂起——为什么我的警报没有正确发送?

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打印到控制台。。。而我没有在代码中的任何地方指定这一点。。。我该如何摆脱这种情况,以及将自定义报警事件处理程序放在哪里?

谢谢!

如果执行时间超过此时间,我想设置10秒的超时并中止子进程

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

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

您的子进程最初将是perl(好吧,shell,然后是perl),它将在自身上设置一个警报,然后执行(用)$someCommand。然而,挂起的警报在exec() s之间继承。

您的代码所要做的只是在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";
}

最新更新