https://issues.apache.org/SpamAssassin/show_bug.cgi?id=6837

--- Comment #4 from Mark Martinec <[email protected]> ---
$ man perlvar:

$^S     Current state of the interpreter.

  $^S         State
  ---------   -------------------------------------
  undef       Parsing module, eval, or main program
  true (1)    Executing an eval
  false (0)   Otherwise


The problem is a combination of two things:
- spamd sets a __DIE__ signal handler very early during its startup,
  in a BEGIN {} block;
- the $^S variable does not distinguish between an error during parsing,
  and an error in eval during parsing, both are seen by a signal handler
  as $^S being undef.

So what happens is that if a signal is thrown from code read by
a 'require', even an eval {} within that code cannot change the
fact that the $^S is undef (indicating a parser error)
when caught by an outer __DIE__ handler.

Here is a demonstration:

perl -e '
  $SIG{__DIE__} = sub {printf("CAUGHT: /%s/: %s\n",
                       !defined $^S ? "undef" : $^S, $_[0])};
  eval "BEGIN {eval{require Nosuch}}"'

I see a couple of possible workarounds, although none seems perfect:

1. add the:
     local $SIG{__DIE__} = sub {};
   in sub print_version and elsewhere where a late 'require'
   is used which may be throwing a signal;

2. within a __DIE__ signal handler $SIG{__DIE__} = sub { ... }
   change:
     log_message("error", $_[0]) if unless $^S;
   into:
     log_message("error", $_[0]) if defined $^S && !$^S;

3. move declaration of a $SIG{__DIE__} signal handler outside of
   a BEGIN {} block and down past most of the code which dynamically
   calls a 'require', i.e. just before the event loop.

I think the case 3 is the cleanest, although there may still be a
case of a late dynamic call to 'require' some module, like the
Compress::Zlib in spamd, or perhaps something in some plugin.

-- 
You are receiving this mail because:
You are the assignee for the bug.

Reply via email to