alarm#
Schedule a SIGALRM to be delivered to the current process after a
whole number of wallclock seconds.
alarm arms a single per-process countdown timer. When the timer
expires, the kernel delivers SIGALRM; what happens next is entirely
up to the installed signal handler in %SIG. The timer
runs in wallclock time, not CPU time, so a sleeping or blocked process
still receives the signal on schedule (subject to scheduling jitter).
Synopsis#
alarm SECONDS
alarm
With no argument, the value in $_ is used.
What you get back#
The number of seconds remaining on the previous timer, or 0 if
no timer was pending. This lets you save and restore a caller’s alarm
across a nested timed operation:
my $prev = alarm 10;
# ... do something that must finish in 10s ...
alarm $prev; # restore caller's timer
alarm 0 cancels any pending timer and returns the seconds that were
left on it.
Global state it touches#
%SIG— theALRMslot names the handler invoked when the timer fires. Without a handler, the default disposition ofSIGALRMis to terminate the process.$_— read whenalarmis called with no argument.$@— carries thediemessage out of the canonicaleval { alarm ...; ...; alarm 0 }idiom.$!— a blocking syscall interrupted bySIGALRMsets$!toEINTR, but Perl restarts many syscalls automatically on some systems, so you cannot rely on seeingEINTR. Useeval/dieinstead (see below).
The canonical timeout idiom#
Use alarm with eval and die to put a wall-clock
cap on any block of code, including blocking I/O:
eval {
local $SIG{ALRM} = sub { die "timeout\n" }; # \n matters
alarm $timeout;
my $nread = sysread $sock, $buf, 4096;
alarm 0; # cancel on success
};
if ($@) {
die $@ unless $@ eq "timeout\n"; # rethrow others
# ... handle timeout ...
}
Three details are load-bearing:
localscopes the handler to theevalblock so it does not leak to the caller.The
\nin"timeout\n"suppresses the file/line suffix thatdiewould otherwise append, making the exact-match test in$@reliable.alarm 0inside theevalcancels the timer on the success path. Without it, a timer left armed can fire during unrelated code after theevalreturns.
Examples#
Simple wallclock deadline:
$SIG{ALRM} = sub { die "timeout\n" };
eval {
alarm 5;
my $line = <$slow_pipe>; # may block indefinitely
alarm 0;
};
warn "gave up waiting\n" if $@ eq "timeout\n";
Nested timers — save and restore:
my $saved = alarm 30; # remember caller's timer
do_something();
alarm $saved; # put it back
Cancel a pending timer:
my $left = alarm 0; # 0 if none was pending
Periodic tick without Time::HiRes:
$SIG{ALRM} = sub {
print "tick\n";
alarm 1; # re-arm from inside the handler
};
alarm 1;
sleep 10; # do not mix sleep+alarm in real code
Sub-second delay — use Time::HiRes:
use Time::HiRes qw(alarm);
alarm 0.25; # 250 ms
Edge cases#
Integer seconds only. The core
alarmtruncates fractional arguments to whole seconds. For finer granularity, loadTime::HiRes, which exports a replacementalarmthat accepts floats.Scheduling jitter. The signal may arrive up to roughly one second early or late because of how the kernel counts seconds and schedules your process. Treat
alarm Nas a not-before-N-minus-1 bound, not a precise deadline.One timer per process. Each
alarmcall replaces the previous timer; there is no queue. The return value is your only record of what was overwritten.Default disposition is fatal. With no handler installed for
ALRM, timer expiry terminates the process withAlarm clock. Install a handler before arming the timer.Do not mix with
sleep. On many systemssleepis implemented on top ofalarm, so arming one clobbers the other. Pick one per block.EINTRis unreliable. Perl installs signal handlers withSA_RESTARTon many platforms, so aSIGALRMthat interrupts a blocking syscall transparently restarts the call instead of returning with$!set toEINTR. The portable way to enforce a deadline iseval/diefrom the handler, as shown above.Signals are delivered between Perl ops. Inside a tight pure-Perl loop the handler runs at the next safe point, not instantly; a CPU-bound XS call can defer delivery further.
forkclears the timer. Child processes start with no pending alarm regardless of what the parent had armed.execclears the timer on Linux; the replacement process image starts with no pendingSIGALRM.
Differences from upstream#
Fully compatible with upstream Perl 5.42.
See also#
sleep— wallclock delay; often implemented on top ofalarm, so the two do not composedie— raise the exception from theALRMhandler thatevalcatches to implement a timeouteval— catches thediefrom the handler and lets the program recover from a timeout%SIG— where theALRMhandler is installed; the handler decides what the timer meansselect— the four-argument form accepts a floating-point timeout and is an alternative toalarmfor I/O deadlinesTime::HiRes— drop-inalarmreplacement that accepts sub-second floats viasetitimer(2)