从如何为Perl系统调用指定超时限制?
eval {
local $SIG{ALRM} = sub { die "alarm\n" }; # NB: \n required
alarm $timeout;
$nread = sysread SOCKET, $buffer, $size;
alarm 0;
};
if ($@) {
die unless $@ 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 out中的代码。 sysread继续工作。我有一个睡眠时间为30秒的perl脚本,而不是sysread。我的超时设置为10秒。正如预期的那样,执行#timed out中的代码,但脚本继续睡眠。任何输入赞赏
答案 0 :(得分:10)
die
不会导致进程结束,它会引发异常。
现在,如果没有任何异常捕获异常,那么就会结束一个进程,但是你已经code来捕获这个异常。
该过程不会因为您明确阻止其结束而结束。
由于您不清楚自己的行为是什么,可能还有另一种可能性:您使用的是Perl的Windows版本。
alarm
是一个Unix系统调用。它的目的(在经过一定时间后发送信号)在Windows上没有任何意义,因为Windows没有信号。
Perl在某种程度上模仿alarm
,但只是以非常有限的方式。 sleep
很可能是唯一可以被alarm
中断的操作。否则,仅在语句之间检查超时。
因此它不会中断sysread
,但一旦sysread
返回,Perl就会注意到超时到期并模拟信号。
答案 1 :(得分:1)
来自男子警报
alarm() arranges for a SIGALRM signal to be delivered to the calling process in seconds seconds.
在 sigalarm 发送之前,执行到达else块。在 sysread 之前插入 STDIN ,以便 sigalarm 触发预期结果。
答案 2 :(得分:1)
"而不是sysread,我有一个睡眠时间为30秒的perl脚本。我的 超时设置为10秒。正如所料,#timmed中的代码是 执行但脚本继续睡觉。"
真的?
#!/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 ($@) {
print "HERE: $@\n";
}
输出:
#!/usr/bin/perl
use strict;
use warnings FATAL => qw(all);
hello!
HERE: bye! at ./test.pl line 9, <$fh> line 3.
超过预期的3秒;如果我只是使用&#34;睡眠100&#34;而不是文件读取。请注意,如果您生成子进程,警报将不会终止该进程,并且父进程必须等待。在那种情况下,&#34;你好!&#34;当警报触发时,信号处理程序中将出现,但是在子进程执行之前,捕获骰子的eval将不会完成。
答案 3 :(得分:0)
将Linux Perl脚本移植到Windows时遇到了同样的问题。
我解决了......
创建非阻塞套接字
$recsock = IO::Socket::INET->new(
LocalPort => 68,
Proto => "udp",
Broadcast => 1,
Blocking => 0,
) or die "socket: $@";
将$ continue变量添加到超时句柄
# Timeout handle
$SIG{ALRM} = sub {
print "timeout\n";
$continue = 1;
};
并在超时发生时检查$ continue是否为真:
alarm($timeout);
while(1){
$recsock->recv($newmsg, 1024);
eval {
$packet = Net::Package->new($newmsg);
...
};
sleep 0.1;
last if ($continue);
}
alarm(0);