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