Question

I use Log4perl in one of my applications and created my own appender which inherits from Log::Dispatch::Email because I need some special handling of sendmail. This appender worked for some years now, but today I recognized some weird behavior in which $@ doesn't get set as before if I configure Log4perl to use my appender or simply Log::Dispatch::Email itself. I used to catch errors in the following way:

eval { main(); 1; };
if (my $error = $@)
{
  log()->error($error);
  exit(error_no_success());
}
exit(error_success());

If I remove the mail appender from my Log4perl configuration and my application dies in main, $error gets the message and it gets logged within the alternative. The problem now is that when I configure my own descendant of Log::Dispatch::Email or this abstract base class directly, $@ in the above statement is the empty string, resulting in the same error as before isn't recognized anymore. If I write something like eval {} or ... $@ is properly available and can be saved. The following works:

my $error = undef;
eval { main(); 1; } or $error = $@;
my $error2 = $@;
if ($error)
{
  log()->error($error);
  exit(error_no_success());
}
exit(error_success());

$error2 is always the empty string if I configure Log::Dispatch::Email in any way. Of course I don't want to change all my code which uses the first example and used to work before to the second one.

Is there anything wrong with my first example? From my point of view it looks like documented for eval in perldoc and it works without email appenders.

Can you think of any reason why using mail appenders changes the behavior on how or when or whatever Perl sets $@ in my second example? Any workarounds? I already had a look at the sources of Log::Dispatch but couldn't find anything obviously interfering with my code.

Thanks for any hints!

Was it helpful?

Solution

With some help over on PerlMonks I finally found the problem: $@ is unreliable. I already had similar problems before and localized $@ in all my destructors by convention, obviously I missed one, which used to log some debug output. After localizing $@ in this destructor before any logging statements, too, my problem got solved and error trapping worked again. I don't know why the problem only got triggered using Log::Dispatch, as the destructor always logged debug statements before, but whatever... Like suggested on PerlMonks, one should switch to use Devel::EvalError in the future.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top