Timing Out Slow Operations
A common use for signals is to impose time limits on long-running
operations. If you’re on a Unix system (or any other POSIX-conforming
system that supports the ALRM
signal), you can ask the kernel to send your process an ALRM at some point in the future:
use Fcntl ":flock";
eval {
local $SIG{ALRM} = sub { die "alarm clock restart" };
alarm 10; # schedule alarm in 10 seconds
eval {
flock(FH, LOCK_EX) # a blocking, exclusive lock
|| die "can't flock: $!";
};
alarm 0; # cancel the alarm
};
alarm 0; # race condition protection
die if $@ && $@ !~ /alarm clock restart/; # reraiseIf the alarm hits while you’re waiting for the lock, and you
simply catch the signal and return, you’ll go right back into
the flock because Perl
automatically restarts syscalls where it can. The only way out is to
raise an exception through die and
then let eval catch it. (This works
because the exception winds up calling the C library’s longjmp(3) function, which is what
really gets you out of the restarting syscall.)
The nested exception trap is included because calling flock would raise an exception if flock is not implemented on your platform, and
you need to make sure to clear the alarm anyway. The second alarm 0 is provided in
case the signal comes in after running the flock but before getting to the first alarm 0. Without the second alarm, you would risk a tiny race condition—but size doesn’t matter in race conditions; they either exist or they don’t. And we prefer that they don’t. ...
Become an O’Reilly member and get unlimited access to this title plus top books and audiobooks from O’Reilly and nearly 200 top publishers, thousands of courses curated by job role, 150+ live events each month,
and much more.
Read now
Unlock full access