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