Perl / perl5

🐪 The Perl programming language
https://dev.perl.org/perl5/
Other
1.85k stars 524 forks source link

perlipc.pod: fix the "exec from signal handler" example #22136

Open stepnem opened 3 weeks ago

stepnem commented 3 weeks ago

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 de7ba5179657 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.

Leont commented 2 weeks ago

I don't know if something changed since 2011 or if the pertinent changes in commit https://github.com/Perl/perl5/commit/de7ba5179657b89436ba73457f8f93957b43a3f0 were wrong to begin with.

Yeah I may have removed too much in that example.

stepnem commented 2 weeks ago

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 de7ba5179657 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.

Leont commented 2 weeks ago

Perhaps let's also improve the code comment a bit to explain the SA_NODEFER usage.

Maybe, or maybe it should instead use sigprocmask in the sighandler to reset the mask right before the exec. That sounds easier to me.

stepnem commented 2 weeks ago

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.")