-
Notifications
You must be signed in to change notification settings - Fork 527
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
perlipc.pod: fix the "exec from signal handler" example #22136
base: blead
Are you sure you want to change the base?
Conversation
Yeah I may have removed too much in that example. |
This is a partial revert of de7ba51 ("Doc patch to perlipc", 2011-09-11). I tested both the pre-de7ba5179657 and current version of the example program (section "Handling the SIGHUP Signal in Daemons") on Arch Linux (perl v5.38.2 built for x86_64-linux-thread-multi) and OpenBSD -current (perl v5.36.3 built for amd64-openbsd). On both systems, the handler is called only once with the current (broken) version of the example program. With the pre-de7ba5179657 version the handler is called on every delivery of the signal, as expected. POSIX shell test script (perlipc-sighandler.sh): ================================================ -->8-- #!/bin/sh check() { printf '\nTesting %s\n' "$*" "$@" & sleep 1 kill -HUP $! sleep 1 kill -HUP $! sleep 1 kill $! } bad=./perlipc-sighandler-bad.perl good=./perlipc-sighandler-good.perl # from current perlipc.pod (perl5 commit e78caca v5.39.9-35-ge78caca8144e) cat <<\EOF >"$bad" #!/usr/bin/perl use v5.36; use POSIX (); use FindBin (); use File::Basename (); use File::Spec::Functions qw(catfile); $| = 1; # make the daemon cross-platform, so exec always calls the script # itself with the right path, no matter how the script was invoked. my $script = File::Basename::basename($0); my $SELF = catfile( $FindBin::Bin, $script ); # POSIX unmasks the sigprocmask properly $SIG{HUP} = sub { print "got SIGHUP\n"; exec( $SELF, @argv ) || die "$0: couldn't restart: $!"; }; code(); sub code { print "PID: $$\n"; print "ARGV: @argv\n"; my $count = 0; while (1) { sleep 2; print ++$count, "\n"; } } EOF # from perlipc.pod before perl5 commit de7ba51 v5.15.2-343-gde7ba5179657 cat <<\EOF >"$good" #!/usr/bin/perl use v5.36; use POSIX (); use FindBin (); use File::Basename (); use File::Spec::Functions qw(catfile); $| = 1; # make the daemon cross-platform, so exec always calls the script # itself with the right path, no matter how the script was invoked. my $script = File::Basename::basename($0); my $SELF = catfile( $FindBin::Bin, $script ); # POSIX unmasks the sigprocmask properly my $sigset = POSIX::SigSet->new(); my $action = POSIX::SigAction->new("sigHUP_handler", $sigset, &POSIX::SA_NODEFER); POSIX::sigaction(&POSIX::SIGHUP, $action); sub sigHUP_handler { print "got SIGHUP\n"; exec( $SELF, @argv ) || die "$0: couldn't restart: $!"; } code(); sub code { print "PID: $$\n"; print "ARGV: @argv\n"; my $count = 0; while (1) { sleep 2; print ++$count, "\n"; } } EOF chmod +x "$bad" "$good" check "$bad" check "$good" -->8-- Example observed output: ======================== ; ./perlipc-sighandler.sh Testing ./perlipc-sighandler-bad.perl PID: 19120 ARGV: got SIGHUP PID: 19120 ARGV: Testing ./perlipc-sighandler-good.perl PID: 19980 ARGV: got SIGHUP PID: 19980 ARGV: got SIGHUP PID: 19980 ARGV: Cc: Leon Timmermans <fawaka@gmail.com> Fixes: de7ba51 ("Doc patch to perlipc")
"POSIX unmasks the sigprocmask properly" seems rather opaque. Instead, explain the SA_NODEFER motivation directly.
Yeah I may have removed too much in that example.
Thank you for having a look.
Having reread the man page (and relevant parts of POSIX and
Linux docs), I realize the paragraph I restored really talks
about an unrelated issue, which (as mentioned in
de7ba51 commit message) is unlikely to occur nowadays,
so let's keep that removed.
The POSIX::sigaction (and SA_NODEFER) is needed here only
because the signal handler calls exec: by default (with a
plain %SIG handler) the handled signal is blocked (added to
process signal mask) while the handler function runs, but
here it never returns (calling exec) and the signal mask is
preserved across execve, preventing further instances of
the signal from being delivered to the new process.
Perhaps let's also improve the code comment a bit to explain
the SA_NODEFER usage.
|
d8adbe3
to
e676714
Compare
Maybe, or maybe it should instead use |
Instead of using SA_NODEFER, which makes the handler function itself interruptible by another SIGHUP, use a plain $SIG{HUP} handler and unblock SIGHUP using sigprocmask from the main program.
Maybe, or maybe it should instead use `sigprocmask` in the sighandler to reset the mask right before the `exec`
Yeah, although if the concern is avoiding the window for
another SIGHUP in the handler function before exec, wouldn't
it be better to unblock SIGHUP unconditionally in the main
program (outside the handler)?
(Possibly for other reasons as well: after all, the signal
might also be added to procmask by something else before
executing the program; also, the perl POSIX module has the
following caveat for sigprocmask: "Note that you can't
reliably block or unblock a signal from its own signal
handler if you're using safe signals.")
|
@stepnem, we have certain metadata checks that are preventing your pull request from being tested by our continuous integration rig. Could you please do the following:
Please run |
I don't think that is a concern. |
I was scratching my head wondering why my signal handlers
calling exec[1] didn't work, and neither did the perlipc
example.
Fortunately a search turned up
https://www.perlmonks.org/?node_id=440900 which still cites
the old (and apparently still correct) documentation.
I don't know if something changed since 2011 or if the
pertinent changes in commit de7ba51 were wrong to begin
with.
For convenience I've also put the test script demonstrating
the issue (included in the commit message, with further
details) into a gist:
https://gist.github.com/stepnem/738d7d2e21bc4ab3d1d0a715c4a8bf86
[1] Note that the exec seems important; a simpler handler
(e.g., just printing or setting a variable) appears to work
fine without POSIX.