Basic exception handling in Perl
The most basic way to handle exceptions in Perl is to use an?eval BLOCK?and have?$@?transmit the error.
1
2
3
4
5
6
|
eval
{?????????????????????????
# try
????
...run the code here....
1;
} or
do
{??????????????????????
# catch
...handle the error using $@...
};
|
Because the?eval?block ends with a true statement,it will always return true if it succeeds and false otherwise.
$@?can be a simple string,reference or an object,and is "thrown" by?die
Dangers of using $@
The more common,but subtly flawed,idiom is to check?$@?to see if the?eval?failed.
# FLAWED!
{??????????????????????????
# try
...run the code here...
};
if
( $@ ) {??????????????????????
# catch
...handle the error using $@...
}
|
This method is essentially non-atomic and has proven finicky. The problem lies with using?$@. As it is global and there are many things which can reset it,either intentionally or otherwise,between the eval block failing and when it is checked.
Useful CPAN modules for exception handling in Perl
Two modules,in particular,are commonly used to implement more intricate exception mechanisms:
- Error?provides exception classes with throw/try/catch syntax sugar with subroutine prototypes and anonymous subroutines. (Used by ~80 CPAN distributions)
- O'Reilly Article
- Exception::Class?provides exception classes using the built-in?eval?syntax. (Used by ~60 CPAN distributions)
- DDJ Article
- Using Exception::Class?thread on perlmonks
Other modules are useful for checking exception handling during testing:
- Test::Exception
- Test::Trap
Discussions on the pros and cons of exception handling
- Best Practices for Exception Handling
Re: The Dangers of using $@..... is it really that bad? In 10+ years of using Perl I've never hit a problem with it...
contributed by??on?Dec 13,2007 5:43am
I'm not sure that I would worry to much about the?Flawed?example as well. I would change it to reassign the $@ to an error variable before doing anything else. e.g. my $err = $@; if ( $err ) { handle_error( $err ); }
_contributed by??lecar red?on?Dec 20,2007 9:35am?_
Re: Using $@.
I used to not worry about it,but lately it's been biting me in the ass. Once I discovered the simple eval {} or do {} idiom,rather than the messier: my $eval = eval {}; unless( $eval ) {} there's really no reason to use $@ for simple exceptions.
contributed by??on?Dec 25,2007 3:33pm
Re: Using $@.
Could you provide a little example of such a situation? Is this thread-related or can it happen even to non-threaded programs? It seems strange that something can get in the path between the eval and the if,and modify $@,unless maybe if there's been some manipulation with $SIG{__DIE__} (note that I don't know exactly what I'm talking about,hence I'm asking :)
contributed by??on?Jan 4,2008 9:22am