I doubt that PBP (2005) is up to date with the latest developments in this area. The recently released (2010) 2nd edition of Effective Perl Programming by brian_d_foy recommends the CPAN Try::Tiny module (released 2009) and the new core autodie pragma (added to perl 5.10.1 in 2009): see items 101 ("Use die to generate exceptions") and 103 ("Handle exceptions properly"). In particular, item 103 summarizes with "handling $@ is tricky, but Try::Tiny does it correctly". Note that Try::Tiny has zero dependencies.

2015 update: The excellent Modern Perl book by chromatic also recommends Try::Tiny; from its "Style and Efficacy" chapter, "Exception Caveats" sub-section:

Using $@ correctly requires you to navigate several subtle risks:

use feature 'try' (2023 update: for perl 5.38+)

As clarified with a complete perl v5.38 example program, note that perl v5.34 added try/catch syntax, inspired by Syntax::Keyword::Try:

use feature 'try'; try { do_a_thing(); } catch ( $e ) { warn "It failed - $e"; }

perl v5.36 added finally blocks to try/catch, also inspired by Syntax::Keyword::Try:

use feature 'try'; try { do_a_thing(); } catch( $e ) { ... } finally { cleanup(); }

Note that try-catch feature is no longer experimental with perl v5.40 - its use without a finally block no longer prints a warning but it still must be enabled with the 'try' feature. The optional finally block is still considered experimental and emits a warning, except when explicitly disabled with no warnings "experimental::try";.

Some perldoc References

Exception Safety and RAII

RAII (Resource Acquisition is Initialization) is very useful when throwing exceptions in Perl (via die).

To give a very simple example, this code:

use strict; use warnings; sub fred { my $fname = 'f.tmp'; open( FH, '<', $fname ) or die "error: open '$fname': $!"; print "file '$fname' opened ok\n"; # ... process file here die "oops"; # if something went wrong close(FH); } my $ok = eval { fred(); 1 }; # see [id://11130946] if (!$ok) { print "died: $@\n" } # oops, handle FH is still open if an exception was thrown. my $line = <FH>; print "oops, FH is still open:$line\n";
is not exception-safe because the global file handle FH is not closed when die is called.

A simple remedy is to replace the ugly global FH with a lexical file handle $fh, which is auto-closed at end of scope (RAII):

use strict; use warnings; sub fred { my $fname = 'f.tmp'; open( my $fh, '<', $fname ) or die "error: open '$fname': $!"; print "file '$fname' opened ok\n"; # ... process file here die "oops"; # if something went wrong close($fh); } my $ok = eval { fred(); 1 }; # see [id://11130946] if (!$ok) { print "died: $@\n" } print "ok, \$fh is auto-closed when sub fred exits (normally or via di +e)\n";

References Added Later

Some useful recent Perl Monks nodes: