进程挂起-未交付SIGALRM-Perl

进程挂起-未交付SIGALRM-Perl,perl,Perl,我有一个正在使用openwithpipe执行的命令,我想设置一个10秒的超时时间,如果执行时间超过这个时间,就中止子进程。但是,我的代码只会导致程序挂起-为什么我的闹钟没有正确发送 my $pid = 0; my $cmd = "someCommand"; print "Running Command # $num"; eval { local $SIG{ALRM} = sub { print "alarm \n";

我有一个正在使用openwithpipe执行的命令,我想设置一个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=0;
my$cmd=“someCommand”;
打印“运行命令#$num”;
评估{
本地$SIG{ALRM}=sub{
打印“报警\n”;
杀死9美元;
};              
警报10;
pid=打开(my$fh,“$cmd |”);
报警0;
};
如果($@){
除非$@eq“报警\n”,否则将导致死亡;
}否则{
打印$while();
}
编辑:

从下面的答案来看,这就是我的答案:

my $pid = open(my $fh, qq(perl -e 'alarm 10; exec \@ARGV; die "exec: $!\n" ' $cmd |));
print $_ while(<$fh>);
my$pid=open(my$fh,qq(perl-e'alarm 10;exec\@ARGV;die'exec:$!\n'$cmd |));
打印$while();
但是,当闹钟超时时,这会将闹钟打印到控制台上……而我在代码中的任何地方都没有指定这一点……我如何才能摆脱它,我将把自定义闹钟事件处理程序放在哪里

谢谢

我想设置一个10秒的超时时间,如果执行时间超过这个时间,就中止子进程

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

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

您的子进程最初是perl(好的,是shell,然后是perl),它将在自身上设置警报,然后执行(将自身替换为)
$someCommand
。然而,挂起的报警是。

您的代码所做的只是在
打开
调用上设置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";
}
eval{
本地$SIG{ALRM}=sub{
打印“报警\n”;
杀死9美元;
};              
警报10;
$pid=打开(my$fh,“$cmd |”);
边打印边打印;
收盘价$fh;
报警0;
};
如果($@){
除非$@eq“报警\n”,否则将导致死亡;
}

谢谢。我可以为每个执行器重置警报吗?如果警报响起,我将如何处理?比如,我应该把处理代码放在哪里?谢谢,@ikegami。我拒绝这样做,因为我怀疑“someCommand”实际上可能是“someCommand--with=blank separated args”。@user6561,每个exec()都会重置警报。它对于每个派生的进程都是唯一的。关于错误处理,您会注意到生成的进程终止后,
$?
中的信号死亡。在我的系统上,
$?&127==14
(14是SIGALRM)。有关更多详细信息,请参阅文档。好的,我理解,非常感谢!还有两个问题:1。在Perldoc上,它说exec不会返回..那么在这种情况下,我们如何能够在exec上方设置警报并等待它呢?二,。当警报超时时,执行进程是否死亡?@user6561,您的perl脚本将生成一个子进程。该子进程最初是一个新的perl进程。第二个perl进程在自身上设置一个警报。然后,它将其进程映像(
exec()
)替换为“someCommand”的进程映像。这个新的进程映像是一个不同的程序,但保留了第二个perl进程的一些属性:PID、父进程(也就是说,我们仍然是顶级perl脚本的子进程)、进程组、会话、权限(通常)、挂起的内核警报等等,但是在发出警报信号时杀死整个程序…您知道为什么会发生这种情况吗?呃,…,不。它是否在
if($@){…}
块中执行
die
函数?
$@
的内容是什么?