Beefy Boxes and Bandwidth Generously Provided by pair Networks
Perl: the Markov chain saw
 
PerlMonks  

Custom SIG DIE handler that isn't executed in evals

by tunafish (Beadle)
on Sep 14, 2016 at 00:04 UTC ( #1171701=perlquestion: print w/replies, xml ) Need Help??
tunafish has asked for the wisdom of the Perl Monks concerning the following question:

perlvar says this:

Due to an implementation glitch, the $SIG{__DIE__} hook is called even inside an eval(). Do not use this to rewrite a pending exception in $@ , or as a bizarre substitute for overriding CORE::GLOBAL::die() . This strange action at a distance may be fixed in a future release so that $SIG{__DIE__} is only called if your program is about to exit, as was the original intent. Any other use is deprecated.

Is there a work-around for this? I would like to have a production script e-mail me whenever it encounters a fatal error. A die inside an eval is not such a circumstance.

It looks like a possible work around could be to check Carp's longmess() and see if the stack contains an eval at any point. But I'm not sure what other consequences this might have. Am I thinking in the right direction?

  • Comment on Custom SIG DIE handler that isn't executed in evals

Replies are listed 'Best First'.
Re: Custom SIG DIE handler that isn't executed in evals
by RonW (Vicar) on Sep 14, 2016 at 01:32 UTC

    I suggest reverting the sig die handler before the eval, then restore it, after.

    Maybe something like this:

    # untested my $defaultSigDie = $SIG{__DIE__}; $SIG{__DIE__} = \&SigDieHandler; sub doEval { my $savedHandler = $SIG{__DIE__}; $SIG{__DIE__} = $defaultSigDie; my $result = eval $_[0]; $SIG{__DIE__} = $savedHandler; return $result; }

    Untested. YMMV

    Update: Forgot about local (Thanks, anony monk)

    # untested my $defaultSigDie = $SIG{__DIE__}; $SIG{__DIE__} = \&SigDieHandler; sub doEval { local $SIG{__DIE__} = $defaultSigDie; my $result = eval $_[0]; return $result; }

      Hi, thats what local does for globals :) it saves the value until the end of the scope/block

      { local $SIG{__DIE__} = ...; } ## no sig handler here doEval(); sub doEval { local $SIG{__DIE__} = ...; ... } ## the end
        But what to do when the eval is deep within a bunch of system modules? I'm receiving e-mails right now from my script because of an eval located in /usr/local/lib64/perl5/XSLoader.pm
Re: Custom SIG DIE handler that isn't executed in evals
by rminner (Hermit) on Sep 14, 2016 at 10:03 UTC
    I am using a custom die handler for unhandled fatal errors in my script. You can check with $^S whether you are inside an eval block. Anonymous Monk already mentioned $^S in a post above, nevertheless i decided to follow up with a simplified concrete example of what i am using:
    use strict; use warnings; use Carp; local $SIG{__DIE__} = sub { return if ($^S);# only trigger if not inside an eval block print STDERR "global die handler: ".Carp::longmess(@_); exit 1; }; eval { die "die_inside_eval!\n"; }; if ($@) { print "caught eval exception: $@\n"; } die "die_outside_eval!\n";
    output
    caught eval exception: die_inside_eval! global die handler: die_outside_eval! at dietest.pl line 19.
Re: Custom SIG DIE handler that isn't executed in evals
by Beechbone (Friar) on Sep 14, 2016 at 10:40 UTC
    Doing that from inside the script is not a good idea. That way you won't cover all error cases.

    I'd recommend to wrap your script in another one that does that checks and sends you an email if needed.


    Search, Ask, Know

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://1171701]
Approved by stevieb
Front-paged by stevieb
help
Chatterbox?
and all is quiet...

How do I use this? | Other CB clients
Other Users?
Others examining the Monastery: (5)
As of 2017-11-18 04:00 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?
    In order to be able to say "I know Perl", you must have:













    Results (277 votes). Check out past polls.

    Notices?