1

I have code that is occasionally running into a fatal error after running for several hours and I'm not sure why. I'm trying to use a custom $SIG{__DIE__} handler to catch these unexpected terminations, but doing so interferes with my modification of CORE::GLOBAL::die (derived from @ikegami's helpful modification of CORE::GLOBAL::exit that he suggested to me on another question). $SIG{__DIE__} seems to take precedence over CORE::GLOBAL::die, but CORE::GLOBAL::die only fires when die is explicitly called, not when there is an error.

What I would like is to have my custom handler only fire on actual errors whereas my custom CORE::GLOBAL::die can be allowed to handle direct calls to die.

Here's my code:

local $SIG{__DIE__} = \&customErrorHandler;

BEGIN {
    *CORE::GLOBAL::die = sub(;$) {
        &SAFARI::Core::safariErrorLogWriter('Die called.') unless $main::handleDeathLog;

        last EXIT_OVERRIDE if $main::override_exit;
        say STDERR 'Actually going to die now.';
        CORE::die($_[0] // 0);
    };  
}

Given this code, &customErrorHandler is called instead of CORE::GLOBAL::die even when I directly call die. I considered making the DIE handler call CORE::GLOBAL::die, but that has two issues:

  1. The call to the label last EXIT_OVERRIDE works fine when the routine is called with die, but not if there is an error, so my error handler causes an error itself then.

  2. To deal with that, I thought about wrapping the call to CORE::GLOBAL::die to disable that label call in cases of an actual error:

$SIG{__DIE__} = sub { $main::override_exit = 0; die; };

However, SAFARI::Core::safariErrorLogWriter uses caller() to get details to log. If it is called sometimes only one level away from the issue (when die is called directly) and sometimes two levels away (when the handler uses the anonymous wrapper sub to call die), sometimes caller will need to be caller(1) and sometimes caller(2).

Timothy R. Butler
  • 1,097
  • 7
  • 20
  • I gota little lost along the way ... so do you want custom code to run for (certain kinds of?) errors (`customErrorHandler` in `$SIG{__DIE__}`) but other custom code to run when `die` is called explicitly (given in `CORE::GLOBAL::die`) ...? – zdim Apr 22 '21 at 06:07
  • I don't see that the `SIG{__DIE__}` hook overrides `CORE::GLOBAL::die` for direct call to `die` ...? `perl -wE'BEGIN { *CORE::GLOBAL::die = sub(;$) { say "global (@_)" } }; $SIG{__DIE__} = sub { say "hook (@_)" }; die "bye"; say "done"'` – zdim Apr 22 '21 at 06:08
  • @zdim Correct, I want to handle die one way, but handle things that unintentionally cause the script to die another way. That's interesting regarding your test code -- I need to investigate further and figure out why it doesn't play out the same way with mine. Hmm... – Timothy R. Butler Apr 22 '21 at 06:48
  • There is a `CORE::die` in the `CORE::GLOBAL::die` sub so the `$SIG{__DIE__}` hook (handler) probably fires for _that_ (along with more happening), or for some other code in there – zdim Apr 22 '21 at 08:42
  • @zdim I think that makes perfect sense. I've been trying to figure out why the issue occurs on the command line but not in CGI. But when it is running as a CGI script, it avoids that `CORE::die`. Thank you! I'm trying to throw things at it to see if I'm missing something, but I think that's the ticket. – Timothy R. Butler Apr 22 '21 at 17:28
  • Alright, great if that clears it up. Drop a note here once you resolve it... – zdim Apr 23 '21 at 09:23

0 Answers0