knorv
knorv

Reputation: 50117

Ways to do timeouts in Perl?

I frequently use the following pattern to set an upper bound to the running time of a particular code fragment in 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.
}

My questions:

Upvotes: 22

Views: 26142

Answers (3)

Peter V. Mørch
Peter V. Mørch

Reputation: 15907

You could also try Time::Out. I like the syntax and nested timeouts are supported..

Upvotes: 5

Jeff Ober
Jeff Ober

Reputation: 5027

Take care with signal handling. Perl receives signals asynchronously and they may be lost or interfere with each other if a signal is received while another signal is being handled by the callback.

Event-handling libraries' Win32 support is pretty so-so in Perl (I have to support non-cygwin Win32), so I generally use a simple polling loop for timeouts:

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);

The sleep timer can be easily made user- or caller-configurable and unless you are doing an extremely tight loop or have multiple callers waiting on the loop (where you can end up with a race or dead lock), it is a simple, reliable, and cross-platform way to implement a timeout.

Also note that the loop overhead will mean that you cannot guarantee that the timeout is observed absolutely. $test_condition, the decrement, garbage collection, etc. can interfere.

Upvotes: 2

cjm
cjm

Reputation: 62099

You probably want to look at Sys::SigAction. I haven't used it myself, but it has some glowing reviews.

One thing to watch out for is if "stuff that might timeout" uses sleep or alarm itself. Also, in the error handling code, I assume you're prepared for errors other than a timeout.

Upvotes: 10

Related Questions