Several things may go wrong in any program, including problems in programming, bad or missing input, unreachable external resources, and more. Perl doesn’t have any built-in error handling. It knows when it can’t do something, and it can tell me about errors, but it’s up to me as the Perl programmer to ensure that my program does the right thing and when it can’t, to try to do something useful about it.
Many of the concepts I cover in this chapter show up in various Perl modules, but I don’t want this to be a survey of Perl modules. Not only might that be out of date by the time you get this book, but as a Perl master you already know how to browse CPAN. Think about the concepts I present and evaluate those modules with what you’ve learned.
Perl has five special variables it uses to report errors: $!
, $?
, $@
,
$^E
, and ${^CHILD_ERROR_NATIVE}
. Each reports different
sorts of errors. Table 11-1 shows the five
variables and their descriptions, which are also in perlvar:
The simplest errors occur when Perl asks the system to do something, but the
system can’t or doesn’t do it for some reason. In most cases the Perl
built-in returns false and sets $!
with the error message. If I try to read a file that isn’t there,
open
returns false and puts the reason it failed in $!
:
open my $fh, '<', 'does_not_exist.txt' or die "Couldn't open file! $!";
The Perl interpreter is a C program, and it does its work through
the library of C functions it’s built upon. The value of $!
represents the result of the call to the
underlying C function, which comes from the errno.h header file. That’s the one from the
standard C library. Other applications might have a file of the same
name. The errno.h file associates
symbolic constants with each error value and gives a text description
for them. Here’s an excerpt from the errno.h file from Mac OS X:
#define EPERM 1 /* Operation not permitted */ #define ENOENT 2 /* No such file or directory */ #define ESRCH 3 /* No such process */
In my open
example
I interpolated $!
in a string and got
a human-readable error message out of it. The variable, however, has a
dual life. Scalars that have different string and numeric values are
known as dualvars.
The numeric value is the errno
value from the C function, and the string value is a human-readable
message. By setting $!
myself I can
see both values. I use printf
’s
format specifiers to force both the numeric and string versions of the
same scalar:
for ($! = 0; $! <= 102; $!++) { printf("%d: %s\n", $!, $! ); }
The output shows the numeric value as well as the string value:
1: Operation not permitted 2: No such file or directory 3: No such process ...
The value of $!
is only
reliable immediately after the library call. I should only use $!
immediately after the expression I want to
check. My next Perl statement might make another library call, which
could again change its value, but with a different message. Also, a
failed library call sets the value, but a successful one doesn’t do
anything to it and won’t reset $!
. If
I don’t check the value of $!
right
away, I might associate it with the wrong statement.
That’s not the whole story, though. The %!
hash has some
magic to go along with $!
. The keys to
%!
are the symbolic constants, such
as ENOENT
, from errno.h. This is a magic hash, so only the
key that corresponds to the current $!
has a value. For instance, when Perl can’t
open my does_not_exist.txt, it sets
$!
with the value represented by
ENOENT
. At the same time, Perl sets
the value of $!{ENOENT}
. No other
keys in %!
will have a value. This
means I can check what happened when I try to recover from the failed
open
by
taking appropriate action based on the type of error.
If Perl sees %!
anywhere in the
program, it automatically loads the Errno
module, which provides functions with the same name as the
errno.h symbolic constants so I can
get the number for any error. I don’t have to use %!
to get this, though. I can load it myself,
and even import the symbols I want to use:
use Errno qw(ENOENT); print 'ENOENT has the number ' . ENOENT . "\n";
In this example program, I want to write some information to disk.
It’s very important information, so I want to take extra care to ensure
I save it. I can’t simply die
and
hope somebody notices. Indeed, if I can’t write to the file because the
disk is full, my warning may never even make it to a log file:
#!/usr/bin/perl use File::Spec; my $file = 'does_not_exist.txt'; my $dir = 'some_dir'; my $fh; my $try = 0; OPEN: { last if $try++ >= 2; my $path = File::Spec->catfile( $dir, $file ); last if open $fh, '>', $path; warn "Could not open file: $!...\n"; if( $!{ENOENT} ) { # File doesn't exist # Ensure the directory is there warn "\tTrying to make directory $dir...\n"; mkdir $dir, 0755; } elsif( $!{ENOSPC} ) { # Full disk # Try a different disk or mount point warn "\tDisk full, try another partition...\n"; $dir = File::Spec->catfile( File::Spec->rootdir, 'some_other_disk', 'some_other_dir' ); } elsif( $!{EACCES} ) { # Permission denied warn "\tNo permission! Trying to reset permissions...\n"; system( '/usr/local/bin/reset_perms' ); } else { # give up and email it directly... last; } redo; } print $fh "Something very important\n";
Though this is a bit of a toy example, I can see that I have a lot
of power to try to recover from a system error. I try to recover in one
of four ways, and I’ll keeping running the naked block I’ve labeled
with OPEN
until it
works or I’ve tried enough things (at some point it’s hopeless, so I
give up). If I can open the filehandle, I break out of the naked block
with last
. Otherwise, I look in
%!
to see which key has a true value.
Only one key will hold a true value, and that one corresponds to the
value in $!
. If I get back an error
saying the file doesn’t exist, I’ll try to create the directory it’s
going to so I know it’s there. If there’s no space left on the disk,
I’ll try another disk. If I don’t have the right permissions, I’ll try
to reset the permissions on the file. This used to be a big problem at
one of my jobs. A lot of people had admin privileges and would do things
that inadvertently changed permissions on important files. I wrote a
setuid program that pulled the right permissions from a database and
reset them. I could run that from any program and try the open
again.
That sure beats a phone call in the middle of the night. Since then,
I’ve realized the lack of wisdom in letting just anyone be root.
To tell me what went wrong with subprocesses that my programs start, Perl uses
$?
to let me see the child process
exit status. Perl can communicate with external programs through a
variety of mechanisms, including:
system( ... ); `...`; open my $pipe, "| some_command"; exec( 'some command' ); my $pid = fork(); ...; wait( $pid );
If something goes wrong, I don’t see the error right away. To run
an external program, Perl first forks, or makes a copy of the current
process, then uses exec
to turn
itself into the command I wanted. Since I’m already running the Perl
process, it’s almost assured that I’ll be able to run another copy of it
unless I’ve hit a process limit or run out of memory. The first part,
the fork
, will work. There won’t be
any error in $!
because there is no C
library error. However, once that other process is up and running, it
doesn’t show its errors through the $!
in the parent process. It passes its exit
value back to the parent when it stops running, and Perl puts that in
the $?
. I won’t see that error until
I try to clean up after myself when I use close
or wait
:
close( $pipe ) or die "Child error: $?"; wait( $pid ) or die "Child error: $?";
The value of $?
is a bit more
complicated than the other error variables. It’s actually a word (2
bytes). The high byte is the exit status of the child process. I can
shift all the bits to the right eight places to get that number. This
number is specific to the program I run, so I need to check its
documentation to assign the proper meaning:
my $exit_value = $? >> 8;
The lower 7 bits of $?
hold the
signal number from which the process died if it died from a
signal:
my $signal = $? & 127; # or use 0b0111_1111
If the child process dumped core, the eighth bit in the low word is set:
my $core_dumped = $? & 128; # or use 0b1000_000;
When I use Perl’s exit
, the
number I give as an argument is the return value of the
process. That becomes the high word in $?
if some other Perl program is the parent
process. My exit_with_value.pl
program exits with different values:
#!/usr/bin/perl # exit_with_value.pl # exit with a random value exit time % 256;
I can call exit_with_value.pl
with another program, exit_with_value_call.pl. I call the first
program with system
, after
which I get the exit
value by
shifting $?
down eight
positions:
#!/usr/bin/perl # exit_with_value_call.pl system( "perl exit_with_value.pl" ); my $rc = $? >> 8; print "exit value was $rc\n";
When I run my program, I see the different exit values:
% perl exit_with_value_call.pl
exit value was 102% perl exit_with_value_call.pl
exit value was 103% perl exit_with_value_call.pl
exit value was 104
If I use die
instead of exit
, Perl uses the
value 255 as the exit
value. I can
change that by using an END
block and
assigning to $?
just before Perl is
going to end the program. When Perl enters the END
block right
after a die
, $?
has the value Perl intends to use as the
exit value. If I see that is 255, I know it came from a die
and can set the exit value to something
more meaningful:
END { $? = 37 if $? == 255 }
On some systems, Perl might even be able to give me more information about
the error by using the $^E
variable.
These errors typically come from outside Perl, so even though Perl might
not detect a problem using external libraries, the operating system can
set its own error variable.
As far as standard Perl is concerned, the value for $^E
is usually the same as $!
. For the things that perl does itself I’m not going to get extra
information in $^E
. On VMS, OS/2,
Windows, or MacPerl, I might get extra information, though.
That doesn’t mean that platform-specific modules can’t use
$^E
to pass back information. When
they talk to other libraries or resources, Perl isn’t necessarily going
to pick up on errors in those operations. If a library call returns a
result indicating failure, Perl might treat it as nothing special. The
calling module, however, might be able to interpret the return value,
determine it’s an error, and then set $^E
on its own.
For Windows, $^E
has whatever
Win32::GetLastError()
returns. The
Win32
family of modules uses $^E
to pass back error information. I can use
Win32::FormatMessage()
to turn the
number into a descriptive string. The Text::Template::Simple::IO
module, for instance, tries to use the Win32
module to validate a Windows path, and if it can’t do that, it uses
GetLastError
to find out what
happened:
package Text::Template::Simple::IO; if(IS_WINDOWS) { require Win32; $wdir = Win32::GetFullPathName($self->{cache_dir}); if( Win32::GetLastError() ) { warn "[ FAIL ] Win32::GetFullPathName\n" if DEBUG; $wdir = ''; # croak "Win32::GetFullPathName: $^E"; } else { $wdir = '' unless -e $wdir && -d _; } }
On VMS, if $!{VMSERR}
is true,
I’ll find more information in $^E
. Other operating systems may use this
too.
So far I’ve shown how Perl tells me about errors, but what if I want to tell
the programmer about something that went wrong in one of my modules? I
have a few ways to do this. I’m going to use Andy Wardley’s Template
Toolkit to show this, since it has all of the examples I
need. Other modules might do it their own way.
The simplest thing to do, and probably the one that annoys me the
most when I see it, is to set a package variable and let the user check
it. I might even set $!
myself. I mean,
I can do that, but don’t mistake that for an
endorsement. The Template
module sets the $Template::ERROR
variable when something goes wrong:
my $tt = Template->new() || carp $Template::ERROR, "\n";
Package variables aren’t very nice, though. They are bad karma, and
programmers should avoid them when possible. In addition to the package
variable, there is the error
class
method, and it’s a much better choice. Even if I don’t get an object when
I try to create one, I can still ask the Template
class to give me the error:
my $tt = Template->new() || carp Template->error, "\n";
If I already have an object, I can use error
to find out what went wrong with the last
operation with that object. The error
method returns an error object from Template::Exception
. I can inspect the type and description of the
error:
$tt->process( 'index.html' ); if( my $error = $tt->error ) { croak $error->type . ": " . $error->info; }
In this case I don’t need to build the error message myself, since
the as_string
method does it for
me:
$tt->process( 'index.html' ); if( my $error = $tt->error ) { croak $error->as_string; }
I don’t even need to call as_string
since the object will automatically
stringify itself:
$tt->process( 'index.html' ); if( my $error = $tt->error ) { croak $error; }
The main design at play in error handling in Template
is that the return value of a function or method does not report the
error. The return value shouldn’t do more than the function is supposed
to do. I shouldn’t overload the return value to be an error
communicator, too. Sure, I might return nothing when something goes
wrong, but even a false value has problems, since 0, the empty string,
or the empty list might be perfectly valid values from a successful
execution of the subroutine. That’s something I have to consider in the
design of my own systems.
Suppose I have a function named foo
that returns a string. If it doesn’t work,
it returns nothing. By not giving return
a value, the caller gets no value in
scalar or list context (which Perl will translate to undef
or the empty list):
sub foo { ... return unless $it_worked; ... return $string; }
That’s simple to document and understand. I certainly don’t want
to get into a mess of return values. Down that road lies madness and
code bloat, as even the seemingly simple functions are overrun by code
to handle every possible error path. If foo
starts to return a different value for
everything that goes wrong, I dilute the interesting parts of foo
:
sub foo { ... return -1 if $this_error; return -2 if $that_error; ... return $string; }
Instead, I can store the error information so the programmer can
access it after she notices the call doesn’t work. I might just add an
error
slot to the instance or class
data. In Template
‘s
process
method, if anything goes
wrong, another part of the system handles and stores it. The process
method just returns the error:
# From Template.pm sub process { my ($self, $template, $vars, $outstream, @opts) = @_; ... if (defined $output) { ... return 1; } else { return $self->error($self->{ SERVICE }->error); } }
The error
method actually lives
in Template::Base
, and it does double duty as a method to set and later
access the error message. This function lives in the base class because
it services all of the modules in the Template
family. It’s actually quite slick in its simplicity and utility:
# From Template/Base.pm sub error { my $self = shift; my $errvar; { no strict qw( refs ); $errvar = ref $self ? \$self->{ _ERROR } : \${"$self\::ERROR"}; } if (@_) { $$errvar = ref($_[0]) ? shift : join('', @_); return undef; } else { return $$errvar; } }
After getting the first argument, it sets up $errvar
. If $self
is a reference (i.e., called as $tt->error
), it must be an instance, so it
looks in $self->{_ERROR}
. If
$self
isn’t a reference, it must be a
class name (i.e., called as Template->error
), so it looks in the
package variable to get a reference to the error object. Notice that
Andy has to turn off symbolic reference checking there so he can
construct the full package specification for whichever class name is in
$self
, which can be any of the
Template
modules.
If there are additional arguments left in @_
, I must have asked error
to set the message, so it does that and
returns undef
. Back in process
, the return value is just what the
error
method returns. On the other
hand, if @_
is empty it must mean
that I’m trying to get the error message, so it dereferences $errvar
and returns it. That’s what I get back
in $error
in my program.
That’s it. Although I may not want to do it exactly the way that Andy did, it’s the same basic idea: put the data somewhere else and give the programmer a way to find it. Return an undefined value to signal failure.
Perl doesn’t have exceptions. Let’s get that clear right now. Like some other things Perl doesn’t really have, people have figured out how to fake them. If you’re used to languages such as Java or Python, set the bar much lower so you aren’t too disappointed. In those other languages exceptions are part of the fundamental design, and that’s how you’re supposed to deal with all errors. Exceptions aren’t part of Perl’s design, and it’s not how Perl programmers tend to deal with errors. However, Perl people still call these things “exceptions” and I will too.
Although I’m not particularly fond of exceptions in Perl, there’s a decent argument in favor of them: the programmer has to catch the error or the program stops. This doesn’t mean, however, the the programmer has to do anything other than ignore the error. But, even not ignoring the error, Perl doesn’t allow the program to pick up where it left off.
Having said all that, though, I can fake rudimentary exceptions. The
easiest method uses a combination of die
and
eval
. The die
throws the exception (meaning I have to do
it on my own) and the eval
catches it
so I can handle it. When eval
catches
an error, it stops the block of code and it puts the error message
into $@
. After the
eval
, I check that variable to see if
something went wrong:
my $result = eval { ...; open my $fh, '>', $file or die "Could not open file! $!"; }; if( defined $@ and length $@ ) { ...; # catch die message and handle it }
The $@
is a tricky variable. If
the eval
executed correctly, it’s the
empty string, which is a false but defined value. It’s not enough to
look for false, which is why I use length
.
I might try to use the result of the eval
to determine if it worked, but then I
have to rely on $result
being
defined. That doesn’t work, for example, if for the last evaluated
expression I call a subroutine that doesn’t create an error but also
doesn’t return a value:
use v5.10; my $result = eval { returns_undef(); }; unless( defined $result ) { say 'result was not defined' } sub returns_undef { return }
To ensure that my eval
block
worked, I can ensure that I return a true value by adding another
statement. Now $result
will only ever
be undefined if the code inside the eval
fails:
use v5.10; my $result = eval { returns_undef(); 1; }; unless( defined $result ) { say 'There was an eval error' } sub returns_undef { return }
The eval
might even catch a
die
several levels away. This “action
at a distance” can be quite troubling, especially since there’s no way
to handle the error, then pick up where the code left off. That means I
should try to handle any exceptions as close to their origin as
possible.
If I use die
as an exception mechanism, I can propagate its message through
several layers of eval
. If I don’t
give die
a message, it uses the
current value of $@
:
#!/usr/bin/perl # chained_die.pl my $result = eval{ eval { eval { # start here open my $fh, '>', '/etc/passwd' or die "$!"; }; if( defined $@ and length $@ ) { die; # first catch } }; if( defined $@ and length $@ ) { die; # second catch } }; if( defined $@ and length $@ ) { print "I got $@"; # finally }
When I get the error message I see the chain of propagations. The
original message Permission denied
comes from the first die
, and each
succeeding die
tacks on a ...propagated
message until I finally get to
something that handles the error:
I got Permission denied at chained_die.pl line 8. ...propagated at chained_die.pl line 11. ...propagated at chained_die.pl line 15.
I might use this to try to handle errors, and failing that, pass
the error up to the next level. I modify my first error catch to append
some additional information to $@
,
although I still use die
without an
argument:
#!/usr/bin/perl # chained_die_more_info.pl my $result = eval{ eval { my $file = "/etc/passwd"; eval { # start here open my $fh, '>', $file or die "$!"; }; if( defined $@ and length $@ ) { my $user = getpwuid( $< ); my $mode = ( stat $file )[2]; $@ .= sprintf "\t%s mode is %o\n", $file, $mode; $@ .= sprintf( "\t%s is not writable by %s\n", $file, $user ) unless -w $file; die; # first catch } }; if( defined $@ and length $@ ) { die; # second catch } }; if( defined $@ and length $@ ) { print "I got $@"; # finally }
I get the same output as I did before, but with my additions. The
subsequent die
s just take on their
...propagated
message:
I got Permission denied at chained_die_more_info.pl line 10. /etc/passwd mode is 100644 /etc/passwd is not writable by Amelia ...propagated at chained_die_more_info.pl line 18. ...propagated at chained_die_more_info.pl line 22.
Exceptions need to provide at least three things to be useful: the type of
error, where it came from, and the state of the program when the error
occurred. Since the eval
may be far
removed from the point where I threw an exception, I need plenty of
information to track down the problem. A string isn’t really good enough
for that.
I can give die
a reference
instead of a string. It doesn’t matter what sort of reference it is. If
I catch that die
within an eval
, the reference shows up in $@
. That means, then, that I can create an
exception class and pass around exception objects. When I inspect
$@
, it has all the object goodness I
need to pass around the error information.
In this short program I simply give die
an anonymous hash. I use the Perl compiler
directives __LINE__
and
__PACKAGE__
to insert the current line number and current package as the
values, and I make sure that __LINE__
shows up on the line that I want to report (the one with die
on it). My hash includes entries for the
type of error and a text message, too. When I look in $@
, I dereference it just like a hash:
#!/usr/bin/perl # die_with_reference.pl my $result = eval { die { 'line' => __LINE__, 'package' => __PACKAGE__, 'type' => 'Demonstration', 'message' => 'See, it works!', }; }; if( defined $@ and length $@ ) { print "Error type: $@->{type}\n" . "\t$@->{message}\n", "\tat $@->{package} at line $@->{line}\n"; }
This works with objects, too, since they are just blessed
references, but I have to make an important change. Once I have the
object in $@
, I need to save it to
another variable so I don’t lose it. I can call one method on $@
before Perl has a chance to reset its
value. It was fine as a simple reference, because I didn’t do anything
that would change $@
. As an object,
I’m not sure what’s going on in the methods that might change it:
#!/usr/bin/perl # die_with_blessed_reference.pl use Hash::AsObject; use Data::Dumper; my $result = eval { my $error = Hash::AsObject->new( { 'line' => __LINE__ - 1, 'package' => __PACKAGE__, 'type' => 'Demonstration', 'message' => 'See, it works!', } ); die $error; }; if( defined $@ and length $@ ) { my $error = $@; # save it! $@ might be reset later print "Error type: " . $error->type . "\n" . "\t" . $error->message . "\n", "\tat " . $error->package . " at line " . $error->line . "\n"; }
Since die
without an argument propagates whatever is in $@
, it will do that if $@
holds a reference. This next program is
similar to my previous chained-die
example, except
that I’m storing the information in an anonymous hash. This makes the
error message easier to use later, because I can pull out just the parts
I need when I want to fix the problem. When I want to change $@
, I first get a deep copy of it (see Chapter 13), since anything I might call could reset
$@
. I put my copy in $error
and use it in my die
. Once I have my reference, I don’t have to
parse a string to get the information I need:
#!/usr/bin/perl # chanined_die_reference.pl my $result = eval{ eval { my $file = "/etc/passwd"; eval { # start here open my $fh, '>', $file or die { errno => $! } }; if( defined $@ and length $@ ) { use Storable qw(dclone); my $error = dclone( $@ ); @{ $error }{ qw( user file mode time ) } = ( scalar getpwuid( $< ), $file, (stat $file)[2], time, ); die $error; # first catch } }; if( defined $@ and length $@ ) { die; # second catch } }; if( defined $@ and length $@ ) { use Data::Dumper; print "I got " . Dumper($@) . "\n"; # finally }
This gets even better if my reference is an object, because I can
handle the propagation myself. The special method named PROPAGATE
, if it exists, gets a chance to
affect $@
, and its return value
replaces the current value of $@
. I
modify my previous program to use my own very simple Local::Error
package to handle the errors. In Local::Error
I skip the usual good
module-programming practices to illustrate the process. In new
I simply bless the first argument into the
package and return it. In my first die
I use as the argument my Local::Error
object. After that, each die
without an argument uses the value of
$@
. Since $@
is an object, Perl calls its PROPAGATE
method, in which I add a new element
to $self->{chain}
to show the file
and line that passed on the error:
#!/usr/bin/perl # chained_die_propagate.pl use strict; use warnings; package Local::Error; sub new { bless $_[1], $_[0] } sub PROPAGATE { my( $self, $file, $line ) = @_; $self->{chain} = [] unless ref $self->{chain}; push @{ $self->{chain} }, [ $file, $line ]; $self; } package main; my $result = eval{ eval { my $file = "/etc/passwd"; eval { # start here unless( open my $fh, '>', $file ) { die Local::Error->new( { errno => $! } ); } }; if( defined $@ and length $@ ) { die; # first catch } }; if( defined $@ and length $@ ) { die; # second catch } else { print "Here I am!\n"; } }; if( defined $@ and length $@ ) { use Data::Dumper; print "I got " . Dumper($@) . "\n"; # finally }
I just dump the output to show that I now have all of the information easily accessible within my object:
I got $VAR1 = bless( { 'chain' => [ [ 'chained_die_propagate.pl', 32 ], [ 'chained_die_propagate.pl', 36 ] ], 'errno' => 'Permission denied' }, 'Local::Error' );
My example has been very simple, but I can easily modify it to use a much more useful object to represent exceptions and specific sorts of errors.
I can propagate errors through nested eval
s and multiple die
s, but
there is a problem. If an eval
block
succeeds, it clears $@
and I lose
anything in that special variable. Since I can use eval
anywhere in a program (and module authors
can use it anywhere without me knowing about it), my error propagation
might fail because of some action at a distance. I can modify my nested
eval
to call some_function
before it die
s:
...; # same as before my $result = eval{ eval { ...; # same as before }; if( defined $@ and length $@ ) { some_function(); die; # second catch } else { print "Here I am!\n"; } }; ...; # same as before sub some_function { # doesn't know about other evals print "In call_some_function\n"; my $quotient = eval { 1 / 1 }; }
The eval
in some_function
succeeds, so it clears $@
. That’s a global variable, so there’s only
one version of it.
I could use local
to try to fix
the overlap in eval
:
sub call_some_function { # doesn't know about other evals my $previous_error = $@; local $@; my $quotient = eval { 1 / 0 }; $@ = $previous_error; return 1; }
This requires that I assume that every eval
is inside some other eval
. It also means that if I die
in call_some_function
, I lose the errors I’ve
built up so far:
sub call_some_function { # doesn't know about other evals my $previous_error = $@; local $@; my $quotient = eval { 1 / 0 }; if( defined $@ and length $@ ) { die; # does not propagate, clobbers $@; } $@ = $previous_error; return 1; }
Sometimes you run a subroutine without explicitly calling it. The
DESTROY
method for an object can run even if the eval
succeeds and there can be another
eval
in there:
{ package Local::Foo; use v5.10; sub new { bless {}, $_[0] } sub DESTROY { say "In DESTROY"; eval { 'True' } } } my $result = eval { my $foo = Local::Foo->new; 1 / 0; }; say "result is undefined" unless defined $result; if( defined $@ and length $@ ) { print "The error is: $@"; }
When I run this, I get different results depending on the version
of perl I use. In versions before
v5.14, the eval
catches the 1 / 0
, sets $@
, and starts to clean up its scope. Since I
created an object in $foo
, that
object gets a chance to call DESTROY
.
In that DESTROY
, I use another
eval
, but this one doesn’t have
anything to catch, so it clears $@
:
% perl5.10.1 eval_with_destroy.pl
In DESTROY
result is undefined
The proper error never shows up! This particular problem is fixed
in v5.14, so when I run with a later perl, $@
has the value that I expect:
% perl5.14.1 eval_with_destroy.pl
In DESTROY
result is undefined
The error is: Illegal division by zero at eval_with_destroy.pl line 18.
The autodie
module, included in the Standard Library since v5.10,
makes exceptions out of errors from Perl built-ins that normally return
false on failure. It uses some of the subroutine wrapping magic I showed
in Chapter 9. I don’t have to check return values
anymore because I’ll catch them as exceptions. I have to specify in the
autodie
import list exactly which functions should do this:
use v5.10; use autodie qw(open); open my $fh, '>', '/etc/passwd';
Instead of silently failing, autodie
causes the program to automatically die when the open
fails:
Can't open '/etc/passwd' for writing: 'Permission denied' at autodie.pl line 3
To catch that I wrap an eval
around my open
to
catch the die
that autodie
installs:
use v5.10; use autodie qw(open); my $file = '/etc/passwd'; eval { open my $fh, '>', $file; }; if( defined $@ and length $@ ) { say $@; }
I can use autodie
with any of the Perl built-ins, but I have to list all of the functions
that I want to affect in the import list or use an import tag that
includes them.
The most interesting part of autodie
is that it uses an object in $@
, and
that object does some string overloading to make it easy for me to check
the sort of error I get. In the example in the module, it makes good use
of given
and when
for that:
use v5.10.1; # the earliest version for current smart-matching eval { use autodie; open(my $fh, '<', $some_file); my @records = <$fh>; # Do things with @records... close($fh); }; given ($@) { when ( '' ) { say "No error"; } when ('open') { say "Error from open"; } when (':io') { say "Non-open, IO error."; } when (':all') { say "All other autodie errors." } default { say "Not an autodie error at all." } }
I could just operate on the object directly, but that looks a lot more messy:
my $result = eval { use autodie; open(my $fh, '<', $some_file); ...; }; my $error = $@; if( eval{ $error->isa('autodie::exception') } ) { if ($error->matches('open')) { print "Error from open\n"; } elsif ($error->matches(':io' )) { print "Non-open, IO error."; } } elsif( $error ) { # A non-autodie exception. }
If I don’t end my die
or warn
message with a newline, Perl adds some source code information at
the end:
#!/usr/bin/perl # die.pl die q(I'm die-ing!);
When I run die.pl, my message includes the name of the file and the line number of the error message:
% perl die.pl
I'm die-ing! at die.pl line 3.
For very simple programs, that extra information might be fine. However, what happens when I have a larger program where I use subroutines?
#!/usr/bin/perl # bal_call.pl bad_call(); sub bad_call { die q(I'm die-ing in bad_call!); }
The die
still reports the file
and line number, but now it’s in the subroutine, so that’s the line number
I get:
% perl bad_call.pl
I'm die-ing! at die.pl line 6.
I rarely find this information interesting. I know that bad_call
is where I encountered the error, but I
want to know where I called that subroutine to cause the problem. Consider
this program, which makes repeated calls to the same subroutine, but only
one of them causes a problem:
#!/usr/bin/perl # divide.pl divide(1, 2); divide(3, 4); divide(4); divide(5, 7); sub divide { my( $numerator, $denominator ) = @_; die q(Can't divide by zero!) if $denominator == 0; $numerator / $denominator; }
I’ve purposely written this program to not output anything, so I can’t tell how far it got before I encountered the error:
% perl divide.pl
Can't divide by zero! at die.pl line 11.
Who’s sending a bad argument to divide
? All I know is that line 11 is where I
discover the problem, not where it actually
is.
The Carp
module, a core module, can fix this. Its croak
function replaces die
:
#!/usr/bin/perl # carp.pl use Carp qw(croak); divide(1, 2); divide(3, 4); divide(4); divide(5, 7); sub divide { my( $numerator, $denominator ) = @_; croak q(Can't divide by zero!) if $denominator == 0; $numerator / $denominator; }
Now, I not only see which line has the bad call, but I get some call trace information. I know that the offending call is on line 8:
% perl carp.pl
Can't divide by zero! at carp.pl line 13.
main::divide(4) called at carp.pl line 8
If I modify my program a little, croak
changes its behavior:
#!/usr/bin/perl # local_math.pl use v5.14; Local::Math->divide(1, 2); Local::Math->divide(3, 4); Local::Math->divide(4); Local::Math->divide(5, 7); package Local::Math { use Carp qw(croak); sub divide { my( $class, $numerator, $denominator ) = @_; croak q(Can't divide by zero!) if $denominator == 0; $numerator / $denominator; } }
Now I don’t get that call trace information:
% perl local_math.pl
Can't divide by zero! at local_math.pl line 6.
This use of Carp
is the
most common. Module authors use croak
in favor of die
because it tells their
module users where they used the module incorrectly, instead of showing an
error from a file that you didn’t write, might not control, or might not
even know you were using.
Carp
tries to
be smart about this. I modify Local::Math::divide
to call an internal, private (by convention) subroutine
_divide
:
#!/usr/bin/perl # private_croak.pl use v5.14; Local::Math->divide(1, 2); Local::Math->divide(3, 4); Local::Math->divide(4); Local::Math->divide(5, 7); package Local::Math { use Carp qw(croak); sub divide { my( $class, $numerator, $denominator ) = @_; _divide( $numerator, $denominator ); } sub _divide { croak q(Can't divide by zero!) if $_[1] == 0; $_[0] / $_[1] } }
This reports the same thing, even though I called _divide
from another subroutine in Local::Math
:
% perl private_croak.pl
Can't divide by zero! at private_croak.pl line 6.
Inside Carp
, croak
looks up through the call stack to find
where the package of the subroutine name changes and considers that the
error comes from there. That makes sense in the real world case; something
outside of the package is probably causing the error. If I put _divide
in a different package, it doesn’t
produce the extra information I saw earlier when it was used from the same
package:
#!/usr/bin/perl # other_package_croak.pl Local::Math->divide(1, 2); Local::Math->divide(3, 4); Local::Math->divide(4); Local::Math->divide(5, 7); package Local::Math { sub divide { my( $class, $numerator, $denominator ) = @_; Local::BaseMath::_divide( $numerator, $denominator ); } } package Local::BaseMath { use Carp qw(croak); sub _divide { croak q(Can't divide by zero!) if $_[1] == 0; $_[0] / $_[1] } }
When I separate the packages, I get a different error message:
% perl other_package_croak.pl
Can't divide by zero! at other_package_croak.pl line 12.
Besides the file and line number differences, croak
mostly acts like die
, so the techniques I showed earlier with
die
still work.
The Carp
module
has a similar function to replace warn
.
carp
outputs the error message just
like croak
, but the program continues.
That way, I get the error message with the file and line number where I
started the problem.
If I need more information about the call stack, I can use confess
to die
with a
backtrace. I don’t find this particularly useful except for debugging, so
I don’t want to hardcode those. Instead, I can use Carp::Always
from the command line to get stack traces when I need to
debug something (and short messages otherwise):
% perl -MCarp::Always script.pl
So far, I’ve shown how I can throw exceptions. When I do that, I need to be able to
catch them. That sounds easy, but due to some of Perl’s historical
limitations, there are plenty of gotchas. I already explained issues with
nested eval
s and propagating die
s, but you don’t have to deal with those on
your own if you can use one of these CPAN modules.
The Try::Tiny
module handles the details of maintaining the error
messages even with nested try
s:
# try.pl use Try::Tiny; try { try { die "die message"; } catch { print "Try in try caught: $_"; }; try_sub(); 1 / 0; } catch { print "Outer try caught: $_"; }; sub try_sub { try { die "die from a subroutine"; } catch { print "Try in subroutine caught: $_"; } }
The output shows that each catch
outputs the message I expect:
% perl try.pl
Try in try caugh: die message at try.pl line 7.
Try in subroutine caught: die from a subroutine at try.pl line 22.
Outer try caught: Illegal division by zero at try.pl line 13.
Since Try::Tiny
uses normal Perl subroutines instead of blocks, a return
inside one of those subroutines doesn’t
return from what you expect might be the right place. In this example, a
simple code inspection probably leads most programmers to expect
try_something
to return Buster
, but it returns Mimi
:
#try_tiny_return.pl use v5.10; use Try::Tiny; my $value = try_something(); say "Value is [$value]"; sub try_something { try { 1 / 0 } catch { say "In catch!"; return "Buster" }; return "Mimi"; }
I can get the return value of the try
-catch
,
but then I have to figure out if it was successsful or not:
#try_tiny_return.pl use v5.10; use Try::Tiny; my $value = try_something(); say "Value is [$value]"; sub try_something { my $value = try { 1 / 0 } catch { say "In catch!"; return "Buster" }; ...; # how to return now? return "Mimi"; }
The *::Tiny
family of modules
provide most of the functionality that people want with
minimal dependencies. The TryCatch
module can have multiple catch
blocks, each targeting a different sort
of exception:
# trycatch_type.pl use v5.10.1; use TryCatch; try { die time % 2 ? bless {}, 'Local::Foo' : "This is just a string" ; } catch (Local::Foo $err) { say "Caught Local::Foo [$err]"; } catch ($err) { say "Caught [$err]"; }
I can use return
as most people
would expect, unlike Try::Tiny
.
This code returns Buster
:
use v5.10.1; use TryCatch; my $value = try_something(); say "value is [$value]"; sub try_something { try { 1 / 0 } catch ($err) { return 'Buster'; } return 'Mimi'; }
This module has some serious problems, however. Its syntax-bending
power comes from Devel::Declare
and other modules that mutate Perl syntax during parsing
(so not as a source filter). This makes it sensitive to changes in Perl.
Furthermore, it fails in certain invocations where competent Perl
programmers would expect it to work. Read through its list of open issues before you
commit yourself to it.
Instead of exceptions, some Perl modules set a global variable and return undef
. The DBI
methods return undef
on
failure, and I have to look in the err
,
errstr
, or state
methods to get an error message:
my $dbh = DBI->connect( ... ); my $sth = $dbh->prepare( ... ); my $rc = $sth->execute; unless( defined $rc ) { my $error = $sth->err; ...; }
However, I have to call these methods immediately, since the module
might overwrite them. These methods also have global variable equivalents
such as $DBI::errstr
, $DBI::err
, and $DBI::state
, but by using those you skip
anything that a subclass might do to interpret the error for you.
There’s a better way than exceptions and global variables, especially when we have to inspect or use those results immediately. I can return objects and use the object to tell me if the value represents an error:
use Local::Result; sub do_something { ...; return Result->error( description => ... ) if $something_went_wrong; return Result->success( ... ); } my $result = do_something( ... ); if( $result->is_error ) { $logger->error( $result->description ); }; my $success_value = $result->value;
This way, the error and success values use the same code path, and I handle them in the same way. I have the object so I don’t need to inspect it immediately; I can save it for later. I don’t have an extra step to get the error.
I developed the ReturnValue
module while I was working on this chapter, but I decided not to
use it as an example. Modules that authors create for books tend to go
unloved, and I think that it’s a simple enough module that you should make
your own based on your particular needs. I use this technique for
application-level code, but I don’t force it on reusable
components.
Perl has many ways to report something that goes wrong, and I have to know which one is appropriate for what am I doing. In addition to the things that Perl can detect, there are errors from operating system libraries and other modules. I didn’t recommend a particular best practice in this chapter but gave you enough to think about as you select a CPAN module or create your own according to your needs.
The perlfunc
entries for die
and eval
explain more of the details of those
functions. The Try::Tiny
documentation explains more details and you should read it
even if you don’t want to use that module.
Arun Udaya Shankar covers “Object Oriented
Exception Handling in Perl” for Perl.com. He shows the Error
module, which provides an exception syntax that looks more
like Java than Perl with its try-catch-finally blocks.
Dave Rolsky wrote “Exception Handling in Perl with Exception::Class” for The Perl Journal (now Dr. Dobb’s Journal).
I wrote “Return error objects instead of throwing exceptions” for The Effective Perler.
Perl Training
Australia has a good discussion of autodie
in “autodie—The art of
Klingon Programming”.
Stack Overflow has many interesting discussions about autodie.
I’ve covered some modules in this chapter, but it wasn’t my intent
to give you a summary of all the modules that can do the same job. I want
you to understand some of the key points, then select something that works
for you. Check similar modules on CPAN by looking into the namespaces that
include Error
,
Exception
,
Ouch
, or
Try
.