在Perl中做超时的方法?

时间:2010-03-11 07:37:49

标签: perl timeout

我经常使用以下模式设置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.
}

我的问题:

  • 这是正确的方法吗?
  • 在任何情况下,运行时间可能超过$ TIMEOUT_IN_SECONDS,还是上述方法防弹?

3 个答案:

答案 0 :(得分:10)

您可能希望查看Sys::SigAction。我自己没有使用它,但它有some glowing reviews

需要注意的一件事是“可能超时的内容”使用sleepalarm本身。此外,在错误处理代码中,我假设您已准备好除超时之外的错误。

答案 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,减量,垃圾回收等都可能会干扰。