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:
The call to the label
last EXIT_OVERRIDE
works fine when the routine is called withdie
, but not if there is an error, so my error handler causes an error itself then.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)
.