Isn't that a rather serious bug in perl (famous last words)? Looking at the code there is no place where a handler capable of dying is possibly called outside eval.

Could a signal get caught while perl was inside the eval block, a Perl-level handler stored somewhere and its execution resumed after the current opcode "exit eval block" finished? But at the ending brace of the eval block the handler should have already been reset.

The problem is that "at the ending brace of the eval block" the handler is not reset.

For that to be the case, it would be necessary to localise the $SIG{ALRM}. But as has been discovered, the serious bug is that the localisation temporarily sets the DEFAULT -- which is horrible.

Anyway, reverting to the empirical approach: to show that the handler set in the eval block remains set after the handler dies and terminates the eval, I modified your test as shown below. The results I got are:

+++ parent entering wrap_sigs loop
$SIG{ALRM}=outr_alrm enter wrap_alrm
$SIG{ALRM}=outr_alrm exit  wrap_alrm (0) $outr=0; $rcvd=0; $dies=0; $wrap=0
$SIG{ALRM}=outr_alrm after sleep         $outr=0; $rcvd=0; $dies=0; $wrap=0
$SIG{ALRM}=outr_alrm enter wrap_alrm
$SIG{ALRM}=outr_alrm exit  wrap_alrm (0) $outr=0; $rcvd=0; $dies=0; $wrap=0
$SIG{ALRM}=outr_alrm after sleep         $outr=0; $rcvd=0; $dies=0; $wrap=0
$SIG{ALRM}=outr_alrm enter wrap_alrm
$SIG{ALRM}=outr_alrm exit  wrap_alrm (0) $outr=0; $rcvd=0; $dies=0; $wrap=0
+++ child starting signal storm
$SIG{ALRM}=outr_alrm after sleep         $outr=1; $rcvd=0; $dies=0; $wrap=0
$SIG{ALRM}=outr_alrm enter wrap_alrm
$SIG{ALRM}=wrap_alrm exit  wrap_alrm (1) $outr=1; $rcvd=1; $dies=1; $wrap=0
$SIG{ALRM}=wrap_alrm after sleep         $outr=1; $rcvd=2; $dies=1; $wrap=1
$SIG{ALRM}=wrap_alrm enter wrap_alrm
$SIG{ALRM}=wrap_alrm exit  wrap_alrm (1) $outr=1; $rcvd=3; $dies=2; $wrap=1
$SIG{ALRM}=wrap_alrm after sleep         $outr=1; $rcvd=4; $dies=2; $wrap=2
$SIG{ALRM}=wrap_alrm enter wrap_alrm
$SIG{ALRM}=wrap_alrm exit  wrap_alrm (1) $outr=1; $rcvd=5; $dies=3; $wrap=2
$SIG{ALRM}=wrap_alrm after sleep         $outr=1; $rcvd=6; $dies=3; $wrap=3
$SIG{ALRM}=wrap_alrm enter wrap_alrm
$SIG{ALRM}=wrap_alrm exit  wrap_alrm (1) $outr=1; $rcvd=7; $dies=4; $wrap=3
$SIG{ALRM}=wrap_alrm after sleep         $outr=1; $rcvd=8; $dies=4; $wrap=4
this shows: I hope this is reasonably clear !

use strict; use warnings ; $| = 1 ; my $outr = 0 ; # count of ALRMs seen by "outer" handler my $rcvd = 0 ; # count of ALRMs seen by "wrap_alrm" handler my $wrap = 0 ; # count of ALRMs seen by "wrap_alrm" handler *outside* + eval my $dies = 0 ; # count of ALRMs seen by "wrap_alrm" signal *inside* + eval my $eval = 0 ; # Flag set while in eval {} in "wrap_alrm" my %handlers = () ; sub wrap_alrm { my $died = $dies ; $eval = 1 ; # NB: there is a race here eval { my $old = $SIG{ALRM} || 'DEFAULT' ; $SIG{ALRM} = sub { $rcvd++ ; if ($eval) { $dies++ ; die ("SIG ALRM $rcvd\n") ; } else { $wrap++ ; } ; } ; $handlers{$SIG{ALRM}} = 'wrap_alrm' ; sleep 1 ; $SIG{ALRM} = $old ; } ; $eval = 0 ; # And a race here, too return $dies - $died ; } my $pid = fork; if ($pid) { $SIG{ALRM} = sub { $outr++ ; } ; $handlers{$SIG{ALRM}} = 'outr_alrm' ; my $timeout = time + 10 ; print "+++ parent entering wrap_sigs loop\n" ; while (time < $timeout) { print "\$SIG{ALRM}=", $handlers{$SIG{ALRM}}, " enter wrap_alrm\n" +; my $died = wrap_alrm() ; print "\$SIG{ALRM}=", $handlers{$SIG{ALRM}}, " exit wrap_alrm ($d +ied) ", "\$outr=$outr; \$rcvd=$rcvd; \$dies=$dies; \$wr +ap=$wrap\n" ; sleep 1 ; print "\$SIG{ALRM}=", $handlers{$SIG{ALRM}}, " after sleep + ", "\$outr=$outr; \$rcvd=$rcvd; \$dies=$dies; \$wr +ap=$wrap\n" ; } ; print "parent survived, killing child\n" ; kill TERM => $pid ; } else { sleep 6 ; print "+++ child starting signal storm\n" ; my $timeout = time + 2 ; while(time < $timeout) { kill ALRM => getppid ; } ; } ;

In reply to Re: [WORKAROUND] Re^4: Setting signal handlers considered unsafe? by gone2015
in thread Setting signal handlers considered unsafe? by gnosek

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post, it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, details, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.