perltimeoutalarmtime-hires

Perl Time::HiRes - the best way to replace regular alarm


I need to implement less-than-a-second timeouts in the DBIx::HA package. Having the following code from that module:

my $timeout = 0;
eval {
    no strict;
    my $h = set_sig_handler(
        'ALRM', 
        sub { $timeout = 1; die 'TIMEOUT'; },
        { mask=>['ALRM'], safe=>1 }
    );
    alarm($DATABASE::conf{_getdbname($dsn)}->{'connecttimeout'});
    $dbh = DBI->connect($dsn, $username, $auth, $attrs);
    alarm(0);
};

I know that there is a core Perl module Time::HiRes, but I never used it before. It also has an alarm() sub - may I just insert use Time::HiRes qw (alarm); before the lines above? Or maybe I should somehow adapt the lines above? I haven't found any obvious example.


Solution

  • You can do exactly as you said. All you need to do is load Time::HiRes and import alarm before you call the code. But please don't put it directly above the code, it's not good practice to have use statements all over the place. It belongs to the top.

    The Time::HiRes doc says (emphazis mine):

    alarm ( $floating_seconds [, $interval_floating_seconds ] )

    The SIGALRM signal is sent after the specified number of seconds. Implemented using setitimer() if available, ualarm() if not. The $interval_floating_seconds argument is optional and will be zero if unspecified, resulting in alarm()-like behaviour. This function can be imported, resulting in a nice drop-in replacement for the alarm provided with perl, see the "EXAMPLES" below.

    Then later on there is this example (quoted verbatim) that nicely shows that you can use floating-point values with alarm now.

    use Time::HiRes qw ( time alarm sleep );
    $now_fractions = time;
    sleep (2.5);
    alarm (10.6666666);