--- name: alarm signature: 'alarm SECONDS' signatures: - 'alarm SECONDS' - 'alarm' since: 5.0 status: documented categories: ["Processes"] --- ```{index} single: alarm; Perl built-in ``` *[Processes](../perlfunc-by-category)* # 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`](../perlvar). 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 ```perl alarm SECONDS alarm ``` With no argument, the value in [`$_`](../perlvar) 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: ```perl 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`](../perlvar) — the `ALRM` slot names the handler invoked when the timer fires. Without a handler, the default disposition of `SIGALRM` is to terminate the process. - [`$_`](../perlvar) — read when `alarm` is called with no argument. - [`$@`](../perlvar) — carries the `die` message out of the canonical `eval { alarm ...; ...; alarm 0 }` idiom. - [`$!`](../perlvar) — a blocking syscall interrupted by `SIGALRM` sets `$!` to `EINTR`, **but** Perl restarts many syscalls automatically on some systems, so you cannot rely on seeing `EINTR`. Use [`eval`](eval) / [`die`](die) instead (see below). ## The canonical timeout idiom Use `alarm` with [`eval`](eval) and [`die`](die) to put a wall-clock cap on any block of code, including blocking I/O: ```perl 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: - [`local`](local) scopes the handler to the `eval` block so it does not leak to the caller. - The `\n` in `"timeout\n"` suppresses the file/line suffix that [`die`](die) would otherwise append, making the exact-match test in `$@` reliable. - `alarm 0` **inside** the `eval` cancels the timer on the success path. Without it, a timer left armed can fire during unrelated code after the `eval` returns. ## Examples Simple wallclock deadline: ```perl $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: ```perl my $saved = alarm 30; # remember caller's timer do_something(); alarm $saved; # put it back ``` Cancel a pending timer: ```perl my $left = alarm 0; # 0 if none was pending ``` Periodic tick without `Time::HiRes`: ```perl $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`: ```perl use Time::HiRes qw(alarm); alarm 0.25; # 250 ms ``` ## Edge cases - **Integer seconds only.** The core `alarm` truncates fractional arguments to whole seconds. For finer granularity, load `Time::HiRes`, which exports a replacement `alarm` that 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 N` as a *not-before-N-minus-1* bound, not a precise deadline. - **One timer per process.** Each `alarm` call 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 with `Alarm clock`. Install a handler *before* arming the timer. - **Do not mix with [`sleep`](sleep).** On many systems [`sleep`](sleep) is implemented on top of `alarm`, so arming one clobbers the other. Pick one per block. - **`EINTR` is unreliable.** Perl installs signal handlers with `SA_RESTART` on many platforms, so a `SIGALRM` that interrupts a blocking syscall transparently restarts the call instead of returning with [`$!`](../perlvar) set to `EINTR`. The portable way to enforce a deadline is [`eval`](eval) / [`die`](die) from 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. - **[`fork`](fork) clears the timer.** Child processes start with no pending alarm regardless of what the parent had armed. - **`exec` clears the timer** on Linux; the replacement process image starts with no pending `SIGALRM`. ## Differences from upstream Fully compatible with upstream Perl 5.42. ## See also - [`sleep`](sleep) — wallclock delay; often implemented on top of `alarm`, so the two do not compose - [`die`](die) — raise the exception from the `ALRM` handler that [`eval`](eval) catches to implement a timeout - [`eval`](eval) — catches the `die` from the handler and lets the program recover from a timeout - [`%SIG`](../perlvar) — where the `ALRM` handler is installed; the handler decides what the timer *means* - [`select`](select) — the four-argument form accepts a floating-point timeout and is an alternative to `alarm` for I/O deadlines - `Time::HiRes` — drop-in `alarm` replacement that accepts sub-second floats via `setitimer(2)`