Hint on local DIE handlers in Eval
David Dick
david_dick at iprimus.com.au
Thu Jan 9 22:17:25 CST 2003
i've never actually used a DIE handler before. Why would you use them?
I understand that intercepting a exception thrown by a die and informing
the user about it in a graceful fashion is a useful thing(tm), but i
tend to use an eval block (or similar such as Error.pm) around the
suspect code and a test afterwards. Is the DIE handler just another
example of TIMTOWTDI, or does it have specific advantages/disadvantages
(not merely gotchas) associated with it?
-dave
Scott Penrose wrote:
> Thought I might share some wisdom on a common code error I have seen
> in my own code as well as others...
>
> DIE handlers are great to change so that you can gracefully tell the
> user. However you must remember that module writers tend to expect the
> die handler to actually do a die, and not an "print STDERR ...; exit 1;".
>
> It is common to find in module code things like...
> eval q{
> use Fred;
> };
> unless ($@) {
> print "Cool Fred exists on this machine";
> }
>
> but of course with the DIE handler set this may fail to pick up the
> error, calling your DIE handler and exiting, when it should have
> continued.
>
> You probably find yourself often writing code like this
>
> eval {
> local $SIG{__DIE__} = sub { die $_[0] };
> Do Stuff Here...
> };
> print "Errors checking here" if ($@);
>
> Which correctly picks up errors in the eval.
>
> So us smart developers start doing our own local DIE handler along the
> lines of...
>
> eval q{
> local $SIG{__DIE__} = sub { die $_[0] };
> use Fred;
> };
> unless ($@) {
> print "Cool Fred exists on this machine";
> }
>
> Of course the problem with our little bit of code above is that when
> perl compiles our string it has not yet set the local die handler. So
> any errors in compile (eg: Fred does not exist as a module) causes the
> root DIE handler to get called, again missing the error and not
> handling it correctly.
>
> So the correct approach is of course...
> {
> local $SIG{__DIE__} = sub { die $_[0] };
> eval q{
> use Fred;
> };
> unless ($@) {
> print "Cool Fred exists on this machine";
> }
> }
>
> (ie: move the local $SIG{__DIE__} outside the string eval, but inside
> a block).
>
> This may seem very obvious to some, but you would be surprised how
> many times I have seen it done and then cause REALLY obscure errors
> when upgrading a CPAN module (Cache::Cache uses the eval q{ use ...}
> approach to check for modules, and does NOT set a local DIE handler)
>
> :-)
>
> Scott
More information about the Melbourne-pm
mailing list