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.