This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
threads::shared: veto signal despatch if locked
authorDavid Mitchell <davem@iabyn.com>
Fri, 4 Jun 2010 16:05:21 +0000 (17:05 +0100)
committerDavid Mitchell <davem@iabyn.com>
Fri, 4 Jun 2010 16:05:21 +0000 (17:05 +0100)
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.

dist/threads-shared/shared.xs

index a1c6925..720e3b6 100644 (file)
@@ -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 */