aufflick has asked for the wisdom of the Perl Monks concerning the following question:

This is one for the monks of dubious purity who don't baulk at the thought of overriding die.

I have a package (with parts borrowed and munged from some existing CPAN modules whose names escape me) that replaces die with a handler to make a useful web error page on die - with stack traces etc.

I just had it throw up a very unusual case. The stack trace shows the following:

my_sybase_error_handler() : die "foo"; Sybase::DBlib nsql() Line: 429 : $db->dbsqlexec; my_app_code() : eval {$dbh->nsql;};
Sybase::DBLib allows you to register an error handler that will be called if dbsqlexec detects an error, which is what gets called in the final instance. Clearly the die should be caught by the eval, but instead my web error page gets displayed.

I'm replacing die by assigning the glob of my web error handler to *CORE::GLOBAL::die. perlvar suggests doing this so I don't have to deal with checking $^S which indicates to me that my handler won't get called when something die's within an eval.

That seems to be wrong in this case. Unfortunately this particular application is running that most unfortunate of perl versions 5.6.0 which may have some bearing on the matter.

Next I'm going to run some tests to see if $^S can be set when my die replacement is called, but since I don't even know if it *is* called in this instance (perhaps it is the stack trace that is lying) then my results may not be conclusive.

Replies are listed 'Best First'.
Re: Overriding CORE::GLOBAL::die and $^S
by saintly (Scribe) on Mar 29, 2007 at 23:49 UTC
    Although I can't say how/why dbsqlexec is overriding your 'die' handler, you might be able to use an alternative:
    $SIG{'__DIE__'} = \&my_die_handler;
    Unless another package changes this setting, this traps anyone's call to 'die'.
    Update: I think I misunderstood what you were saying you did.

    Once you install a new handler for '__DIE__' (or __WARN__), then even 'die's or 'warn's inside of evals will call your code. The handler catches all instances of these calls within the scope of that %SIG modification. One solution to this is to reset the handlers inside the eval block:
    eval { local $SIG{'__DIE__'} = 'DEFAULT'; $dbh->nsql; }