my $ALARM_EXCEPTION = 'alarm clock restart'; eval { local $SIG{ALRM} = sub { die $ALARM_EXCEPTION }; alarm 10; ... long computation ... alarm 0; }; if ($@ && $@ !~ quotemeta($ALARM_EXCEPTION)) { die }
After 10s the alarm goes off,
die
inside the callback is executed and returns a string you choose - 'alarm clock restart'
is good choice because no other normal die
command inside the computation is likely to use it.Since
die $ALARM_EXCEPTION
is executed inside an eval
block, $@
is set but execution of the main script does not terminate. quotemeta just backslashes non-alphanumeric characters that may have a special meaning in regexs. There are no such characters in the case of 'alarm clock restart'
, therefore it will just backslash blanks, which is redundant, but there could be any in the full error message that $@
contains.Outside the block one can check whether a real error or a timeout occurred:
if ($@) { # An error occurred. if ($@ =~ quotemeta($ALARM_EXCEPTION)) { # It was a timeout. die 'Timed out: operation is taking too long'; } else { # It was a real error. die; } }
Previous code just ignored timeouts, but now they are considered errors.
All this eval "dance" is needed because you do not want to overwrite a global
ALRM
signal handler you have no control of. Note that die
without any argument just propagates the error message generated by the computation to the main program.
No comments:
Post a Comment