From: David Mitchell Date: Fri, 4 Jun 2010 16:05:21 +0000 (+0100) Subject: threads::shared: veto signal despatch if locked X-Git-Url: http://git.shadowcat.co.uk/gitweb/gitweb.cgi?a=commitdiff_plain;h=65c7421c80585e0d12a20773935dc01f4ffa3e42;p=p5sagit%2Fp5-mst-13.2.git threads::shared: veto signal despatch if locked This fixes RT #74868: Safe signals changes causing hangs with threads. The basic issue is that due to changes in where safe signals can be despatched, (including now on leaving scope), it's possible for a perl-level signal handler to be called while PL_sharedsv_lock is held. If the handler does locking or manipulation of shared vars, then deadlock can occur. A robust fix for this is to ensure that the signal handler isn't called while we have the lock. This is done using the signal handler hook added in the previous commit. --- diff --git a/dist/threads-shared/shared.xs b/dist/threads-shared/shared.xs index a1c6925..720e3b6 100644 --- a/dist/threads-shared/shared.xs +++ b/dist/threads-shared/shared.xs @@ -1167,6 +1167,23 @@ Perl_shared_object_destroy(pTHX_ SV *sv) } #endif +/* veto signal despatch if we have the lock */ + +#ifdef PL_signalhook + +STATIC despatch_signals_proc_t prev_signal_hook = NULL; + +STATIC void +S_shared_signal_hook(pTHX) { + int us; + MUTEX_LOCK(&PL_sharedsv_lock.mutex); + us = (PL_sharedsv_lock.owner == aTHX); + MUTEX_UNLOCK(&PL_sharedsv_lock.mutex); + if (us) + return; /* try again later */ + CALL_FPTR(prev_signal_hook)(aTHX); +} +#endif /* Saves a space for keeping SVs wider than an interpreter. */ @@ -1184,6 +1201,12 @@ Perl_sharedsv_init(pTHX) #ifdef PL_destroyhook PL_destroyhook = &Perl_shared_object_destroy; #endif +#ifdef PL_signalhook + if (!prev_signal_hook) { + prev_signal_hook = PL_signalhook; + PL_signalhook = &S_shared_signal_hook; + } +#endif } #endif /* USE_ITHREADS */