为什么在报警信号处理程序中不死不死呢?
从我如何指定Perl系统调用的超时限制?为什么在报警信号处理程序中不死不死呢?
eval {
local $SIG{ALRM} = sub { die "alarm\n" }; # NB: \n required
alarm $timeout;
$nread = sysread SOCKET, $buffer, $size;
alarm 0;
};
if ([email protected]) {
die unless [email protected] eq "alarm\n"; # propagate unexpected errors
# timed out
}
else {
# didn't
}
如果发生超时,应该sub { die "alarm\n" };
导致进程结束。我想我无法理解die
。 http://www.cs.cf.ac.uk/Dave/PERL/node111.html表示“die()函数用于退出脚本并显示消息供用户阅读”。但是,对于上面的脚本,脚本将在#timed输出中处理代码。 sysread也继续工作。而不是sysread,我有一个睡眠30秒的perl脚本。我的超时设置为10秒。正如预期的那样,在#timed出来的代码被执行,但该脚本继续sleep.Any输入赞赏
die
不会导致进程结束,它会引发异常。
现在,如果没有发现异常,则会结束一个进程,但您已有code来捕获此异常。
该进程没有结束,因为你明确地阻止它结束。
由于您对所得到的行为并不十分清楚,因此可能存在另一种可能性:您正在使用Windows的Windows版本。
alarm
是一个Unix系统调用。这是非常有用的(经过一段时间后发送信号)在Windows上没有意义,因为Windows没有信号。
Perl在某种程度上模仿alarm
,但只能以非常有限的方式。 sleep
很可能是唯一可以通过alarm
中断的操作。否则,仅在语句之间检查超时。
因此它不会中断sysread
,但是一旦sysread
返回,Perl会注意到超时过期并模拟一个信号。
从男子报警
alarm() arranges for a SIGALRM signal to be delivered to the calling process in seconds seconds.
SIGALARM交付执行到else块之前。在之前插入一个STDIN sysread这样sigalarm触发了预期的结果。
“相反sysread执行的,我有这样的睡了30秒的perl脚本。我 超时设置为10秒。正如预期的那样,#timed出的代码被执行 但脚本继续睡觉。 “
真的吗?
#!/usr/bin/perl
use strict;
use warnings FATAL => qw(all);
eval {
open my $fh, '<', $0 || die;
local $SIG{ALRM} = sub {
print STDERR "hello!\n";
die "bye!";
};
alarm 3;
while (<$fh>) {
print $_;
sleep 1;
}
close $fh;
};
if ([email protected]) {
print "HERE: [email protected]\n";
}
输出:
#!/usr/bin/perl
use strict;
use warnings FATAL => qw(all);
hello!
HERE: bye! at ./test.pl line 9, <$fh> line 3.
超过在预期的3秒;如果我只是使用“睡眠100”而不是文件读取,情况仍然如此。注意,如果你产生一个子进程,,报警不会杀死它,父进程必须等待。那样的话,“你好!”在信号处理程序中将出现警报触发时,但捕获死亡的eval将不会完成,直到子进程。
谢谢。这很有用。你已经报警即睡眠习惯后写的代码是我做的S火焰。但它是在一个单独的脚本。感谢评论,eval不会完成,直到命令完成。虽然这很混乱。如果这在其脚本EVAL父进程结束,那么EVAL已经完成。我希望你能理解我的问题。评论框不允许我直观地解释。再次感谢 – doon 2012-04-18 10:44:05
如果你用'打开我的$ fh'替换'open $ 0',' - ','sleep 10'||死亡;'你就会明白我由于必须等待一个子进程(壳睡眠)的意思。但否则,不,正常的命令不应该阻止警报。 – delicateLatticeworkFever 2012-04-18 12:53:28
我移植一个Linux Perl脚本Windows时有同样的问题。
我要解决它...
创建非阻塞套接字
$recsock = IO::Socket::INET->new(
LocalPort => 68,
Proto => "udp",
Broadcast => 1,
Blocking => 0,
) or die "socket: [email protected]";
添加$继续变量超时处理
# Timeout handle
$SIG{ALRM} = sub {
print "timeout\n";
$continue = 1;
};
,并检查了$继续在发生超时时成为现实:
alarm($timeout);
while(1){
$recsock->recv($newmsg, 1024);
eval {
$packet = Net::Package->new($newmsg);
...
};
sleep 0.1;
last if ($continue);
}
alarm(0);
@doon,添加了辅助的答案。 – ikegami 2012-04-18 09:55:59
谢谢。我正在使用perl的UNIX版本。谢谢你让我知道死是一个例外。我没有意识到这一点, – doon 2012-04-18 10:44:47
@doon,相反,有['出口](http://perldoc.perl.org/functions/exit.html)。但是,通常你想'死掉',因为它允许人们如果他们选择处理错误。 – ikegami 2012-04-18 19:55:12