diff options
author | Leon Timmermans <fawaka@gmail.com> | 2012-05-22 16:58:26 +0200 |
---|---|---|
committer | Leon Timmermans <fawaka@gmail.com> | 2012-05-25 22:42:50 +0200 |
commit | eb3d0a5826dc4202bd1ef751f86b4fa666f52d84 (patch) | |
tree | 6da988c2ffdd84e8e3c6b1b9af89b71ece132f7d | |
parent | 4ea2708986710e9739b5a8ac2ccef0c3a2d896f4 (diff) | |
download | perl-eb3d0a5826dc4202bd1ef751f86b4fa666f52d84.tar.gz |
Block signals during fork (fixes RT#82580)
-rw-r--r-- | pod/perldelta.pod | 6 | ||||
-rw-r--r-- | pp_sys.c | 21 |
2 files changed, 27 insertions, 0 deletions
diff --git a/pod/perldelta.pod b/pod/perldelta.pod index 99b7641b8d..026afbcef6 100644 --- a/pod/perldelta.pod +++ b/pod/perldelta.pod @@ -638,6 +638,12 @@ C<CORE::GLOBAL> override had op checking performed twice. The checking is always idempotent for pure Perl code, but the double checking can matter when custom call checkers are involved. +=item * + +A race condition used to exist around fork that could cause a signal sent to +the parent to be handled by both parent and child. Signals are now blocked +briefly around fork to prevent this from happening [perl #82580]. + =back =head1 Known Problems @@ -4021,10 +4021,31 @@ PP(pp_fork) #ifdef HAS_FORK dVAR; dSP; dTARGET; Pid_t childpid; +#if defined(HAS_SIGPROCMASK) && !defined(PERL_MICRO) + sigset_t oldmask, newmask; +#endif EXTEND(SP, 1); PERL_FLUSHALL_FOR_CHILD; +#if defined(HAS_SIGPROCMASK) && !defined(PERL_MICRO) + sigfillset(&newmask); + sigprocmask(SIG_SETMASK, &newmask, &oldmask); +#endif childpid = PerlProc_fork(); + if (childpid == 0) { + int sig; + PL_sig_pending = 0; + if (PL_psig_pend) + for (sig = 1; sig < SIG_SIZE; sig++) + PL_psig_pend[sig] = 0; + } +#if defined(HAS_SIGPROCMASK) && !defined(PERL_MICRO) + { + dSAVE_ERRNO; + sigprocmask(SIG_SETMASK, &oldmask, NULL); + RESTORE_ERRNO; + } +#endif if (childpid < 0) RETSETUNDEF; if (!childpid) { |