Hint on local DIE handlers in Eval

David Dick david_dick at iprimus.com.au
Thu Jan 9 22:30:26 CST 2003


Bugger, should have hit reply-all....

David Dick wrote:

> 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