Perl FAQ 4.8: How can I do an atexit() or setjmp()/longjmp() in Perl? (Exception handling)

Perl FAQ 4.8

How can I do an atexit() or setjmp()/longjmp() in Perl? (Exception handling)

Perl's exception-handling mechanism is its eval operator. You can use eval as setjmp and die as longjmp. Here's an example of Larry's for timed-out input, which in C is often implemented using setjmp and longjmp:

    $SIG{ALRM} = 'TIMEOUT';
    sub TIMEOUT { die "restart input\n" }
    do { eval { &realcode } } while $@ =~ /^restart input/;
    sub realcode {
      alarm 15;
      $ans = ;
      alarm 0;
    }

Here's an example of Tom's for doing atexit() handling:

    sub atexit { push(@_exit_subs, @_) }
    sub _cleanup { unlink $tmp }
    &atexit('_cleanup');
    eval <<'End_Of_Eval';  $here = __LINE__;
	# as much code here as you want
    End_Of_Eval

    $oops = $@;  # save error message

    # now call his stuff
    for (@_exit_subs) { &$_() }
    $oops && ($oops =~ s/\(eval\) line (\d+)/$0 .
	" line " . ($1+$here)/e, die $oops);

You can register your own routines via the &atexit function now. You might also want to use the &realcode method of Larry's rather than embedding all your code in the here-is document. Make sure to leave via die rather than exit, or write your own &exit routine and call that instead. In general, it's better for nested routines to exit via die rather than exit for just this reason.

In Perl5, it is easy to set this up because of the automatic processing of per-package END functions. These work much like they would in awk. See perlfunc(1) , perlmod(1) and perlrun(1) .

Eval is also quite useful for testing for system dependent features, like symlinks, or using a user-input regexp that might otherwise blowup on you.


Other resources at this site: