Using Eval for Time-Outs
When you call eval
, Perl
makes a note of the next statement to start executing just in case a
die
is invoked somewhere within. Internally,
die
happens to invoke a
longjmp
, so Perl wastes no time at all
transferring control back up to the statement following
eval
, regardless of how deep the stack is. (All
temporary and local variables created in the
eval
‘ed code are automatically garbage
collected.)
The use of setjmp
and longjmp
internally gives us one new technique: aborting blocked system calls
and infinite loops. Let’s say you want to wait at most 10
seconds for the user to type something.[25] If you say
$buf
=
<>
, the program is blocked until the user
deigns to hit a carriage return, but we would like Perl to abort it
after waiting 10 seconds. Generating a time-out is not really a
problem; the built-in function
alarm()
can be used to generate an
ALRM
signal after a given number of seconds, like
this:
$SIG{ALRM} = \&timed_out; alarm(10); # Tells the OS to issue an ALRM signal after 10 seconds $buf = <>; # Go into a blocking read
The procedure timed_out
is called (after 10
seconds) regardless of what Perl happens to be executing at that
time, be it a blocked read
or an infinite loop.
The problem is, how does timed_out
force Perl to
abandon what Perl happened to be doing at the time it was called?
That’s where
eval
/die
come in. Put an eval
around $buf = <>
and a die
inside
timed_out()
, and control will be restored to the
statement following eval
(the ...
Get Advanced Perl Programming now with the O’Reilly learning platform.
O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.