"This caveat can lead to the following race condition -- if the signal handler gets triggered after waitpid($pid, 0) has returned *and* the OS has had enough time to start a new process with the same PID, the new process can mistakenly get the TERM signal. I acknowledge that modern operating systems attempt not to reuse the same PID immediately, but I wouldn't like to rely on that assumption in the code, especially because it will be executing with root privileges and can thus kill any process in the system."

You can put the local handler passing the TERM to the child, as well as the waitpid, in an anonymous block. When the waitpid returns, the anonymous block is exited, the handler is popped off the stack, and whatever previous handler was in effect is now in effect again.

#!/usr/bin/env perl -l use strict; use warnings; use constant SLEEP_TIME => 20; my $pid = fork; die "Can't fork()" unless defined $pid; if ($pid) { local $SIG{TERM} = sub { print "Parent received signal: @_"; die "$$ committing suicide!\n"; }; { local $SIG{TERM} = sub { print "Parent received signal: @_"; print "$$ committing infanticide!"; kill TERM => $pid if kill 0 => $pid; }; print "Parent: $$; Child: $pid"; print "Waiting on child ..."; waitpid($pid, 0); } print "Child terminated."; print "$$ resting ..."; sleep SLEEP_TIME; print "$$ rested and exiting."; } else { print "Child: $$"; local $SIG{TERM} = sub { print "Child received signal: @_"; die "Child died via signal handler.\n"; }; sleep SLEEP_TIME; exit; }

So I ran it first without any intervention; it slept as expected:

Parent: 36789; Child: 36790 Waiting on child ... Child: 36790 Child terminated. 36789 resting ... 36789 rested and exiting.

Next I started it running, then entered "kill -TERM 36797" twice in quick succession:

Parent: 36797; Child: 36798 Waiting on child ... Child: 36798 Parent received signal: TERM 36797 committing infanticide! Child received signal: TERM Child died via signal handler. Child terminated. 36797 resting ... Parent received signal: TERM 36797 committing suicide!

Finally, I entered "kill -TERM 36836" followed by "kill -TERM 36835":

Parent: 36835; Child: 36836 Waiting on child ... Child: 36836 Child received signal: TERM Child died via signal handler. Child terminated. 36835 resting ... Parent received signal: TERM 36835 committing suicide!

— Ken


In reply to Re^3: using waitpid() with signals by kcott
in thread using waitpid() with signals by ristov

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.