From: Lubomir Rintel Date: Thu, 25 Jun 2009 20:57:46 +0000 (+0200) Subject: Don't enqueue pending signals during global destruction X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=commitdiff_plain;h=31c91b4357905486e81f901ad079da5735bdb7ba;p=p5sagit%2Fp5-mst-13.2.git Don't enqueue pending signals during global destruction Global destruction is not signal-safe. PL_psig_pend may already be gone when the signal handler is called (with destruct_level > 0). NULL it before freeing it to prevent a race condition. --- diff --git a/mg.c b/mg.c index e9e4214..05a5092 100644 --- a/mg.c +++ b/mg.c @@ -1316,13 +1316,14 @@ Perl_csighandler(int sig) #endif (PL_signals & PERL_SIGNALS_UNSAFE_FLAG)) /* Call the perl level handler now-- - * with risk we may be in malloc() etc. */ + * with risk we may be in malloc() or being destructed etc. */ #if defined(HAS_SIGACTION) && defined(SA_SIGINFO) (*PL_sighandlerp)(sig, NULL, NULL); #else (*PL_sighandlerp)(sig); #endif else { + if (!PL_psig_pend) return; /* Set a flag to say this signal is pending, that is awaiting delivery after * the current Perl opcode completes */ PL_psig_pend[sig]++; diff --git a/perl.c b/perl.c index e70bf7e..d9ebaca 100644 --- a/perl.c +++ b/perl.c @@ -1233,6 +1233,13 @@ perl_destruct(pTHXx) PL_psig_ptr = (SV**)NULL; Safefree(PL_psig_pend); PL_psig_pend = (int*)NULL; + { + /* We need to NULL PL_psig_pend first, so that + signal handlers know not to use it */ + int *psig_save = PL_psig_pend; + PL_psig_pend = (int*)NULL; + Safefree(psig_save); + } PL_formfeed = NULL; nuke_stacks(); PL_tainting = FALSE;