perl - Signal handler not working with double eval -
i have code timeout long-running process (sleep
in case):
#!/usr/bin/env perl use strict; use warnings; die "usage: $0 sleep timeout\n" unless @argv == 2; ( $sleep, $timeout ) = @argv; $|++; eval { local $sig{alrm} = sub { die "timeout\n" }; alarm $timeout; eval { # long-running process print "going sleep ... "; sleep $sleep; print "done\n"; }; alarm 0; # cancel timeout }; die $@ if $@;
when run ./alarm 5 2
, expect die
saying "timeout". exits 0 , says nothing. works expected when remove inner eval
block (not block's content, eval
) though. can explain why that? thanks.
because trap error in first eval
block , second eval
block not have exception , clears $@
.
eval { local $sig{alrm} = sub { die "timeout\n" }; alarm $timeout; eval { # long-running process print "going sleep ... "; a: sleep $sleep; print "done\n"; }; b: alarm 0; # cancel timeout c:}; die $@ if $@;
$sleep
> $timeout
, @ a:
program throws sigalrm
. signal caught local signal handler , calls die "timeout\n"
. perl sets $@
"timeout\n"
, resumes execution @ b:
. program makes c:
without additional errors. since outer eval
block completed normally, perl clears $@
, , final die
statement not execute.
to seems want do, either
- don't use
eval
on outer block - put
die $@ if $@
call @ end of outer block