in reply to Re^2: using waitpid() with signals
in thread using waitpid() with signals
"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
|
|---|
| Replies are listed 'Best First'. | |
|---|---|
|
Re^4: using waitpid() with signals
by ristov (Initiate) on Jan 21, 2017 at 22:51 UTC |