我经常使用以下模式设置Perl中特定代码片段的运行时间的上限:
my $TIMEOUT_IN_SECONDS = 5;
eval {
local $SIG{ALRM} = sub { die "alarm\n" };
alarm($TIMEOUT_IN_SECONDS);
# do stuff that might timeout.
alarm(0);
};
if ($@) {
# handle timeout condition.
}
我的问题:
答案 0 :(得分:10)
您可能希望查看Sys::SigAction。我自己没有使用它,但它有some glowing reviews。
需要注意的一件事是“可能超时的内容”使用sleep
或alarm
本身。此外,在错误处理代码中,我假设您已准备好除超时之外的错误。
答案 1 :(得分:4)
您也可以尝试Time::Out。我喜欢语法和支持嵌套超时..
答案 2 :(得分:2)
注意信号处理。 Perl异步接收信号,如果在回调处理另一个信号时收到信号,它们可能会丢失或相互干扰。
事件处理库的Win32支持在Perl中非常不错(我必须支持非cygwin Win32),所以我通常使用一个简单的轮询循环来超时:
use Time::HiRes qw(sleep);
sub timeout {
my $timeout = shift;
my $poll_interval = shift;
my $test_condition = shift;
until ($test_condition->() || $timeout <= 0) {
$timeout -= $poll_interval;
sleep $poll_interval;
}
return $timeout > 0; # condition was met before timeout
}
my $success = timeout(30, 0.1, \&some_condition_is_met);
睡眠定时器可以很容易地进行用户或呼叫者配置,除非您正在进行非常严格的循环或让多个呼叫者在循环中等待(最终可能会出现竞赛或死锁),这是一个实现超时的简单,可靠和跨平台的方式。
另请注意,循环开销意味着您无法保证绝对会观察到超时。 $ test_condition,减量,垃圾回收等都可能会干扰。