php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Return to Bug #52784
Patch pcntl_pending_signal_allication.diff revision 2010-09-06 16:10 UTC by nick dot telford at gmail dot com
Patch pcntl_sigprocmask.diff revision 2010-09-06 16:09 UTC by nick dot telford at gmail dot com

Patch pcntl_sigprocmask.diff for PCNTL related Bug #52784

Patch version 2010-09-06 16:09 UTC

Return to Bug #52784 | Download this patch
Patch Revisions:

Developer: nick.telford@gmail.com

Index: ext/pcntl/pcntl.c
===================================================================
--- ext/pcntl/pcntl.c	(revision 302771)
+++ ext/pcntl/pcntl.c	(working copy)
@@ -44,6 +44,8 @@
 #include <sys/resource.h>
 #endif
 
+#include <signal.h>
+
 ZEND_DECLARE_MODULE_GLOBALS(pcntl)
 static PHP_GINIT_FUNCTION(pcntl);
 
@@ -1078,31 +1080,44 @@
 {
 	struct php_pcntl_pending_signal *psig;
 	TSRMLS_FETCH();
+
+	/* block all signals temporarily while handling this signal */
+	sigset_t mask;
+	sigset_t old_mask;
+
+	/* create a mask of all signals */
+	sigfillset(&mask);
+
+	/* block all signals, storing original signal mask in old_mask */
+	sigprocmask(SIG_BLOCK, &mask, &old_mask);
 	
 	psig = PCNTL_G(spares);
-	if (!psig) {
-		/* oops, too many signals for us to track, so we'll forget about this one */
-		return;
-	}
-	PCNTL_G(spares) = psig->next;
+	if (psig) {
+		PCNTL_G(spares) = psig->next;
 
-	psig->signo = signo;
-	psig->next = NULL;
+		psig->signo = signo;
+		psig->next = NULL;
 
-	/* the head check is important, as the tick handler cannot atomically clear both
-	 * the head and tail */
-	if (PCNTL_G(head) && PCNTL_G(tail)) {
-		PCNTL_G(tail)->next = psig;
-	} else {
-		PCNTL_G(head) = psig;
+		/* the head check is important, as the tick handler cannot atomically clear both
+		 * the head and tail */
+		if (PCNTL_G(head) && PCNTL_G(tail)) {
+			PCNTL_G(tail)->next = psig;
+		} else {
+			PCNTL_G(head) = psig;
+		}
+		PCNTL_G(tail) = psig;
 	}
-	PCNTL_G(tail) = psig;
+
+	/* done handling this signal, reset signal mask back to original state */
+	sigprocmask(SIG_SETMASK, &old_mask, NULL);
 }
 
 void pcntl_signal_dispatch()
 {
 	zval *param, **handle, *retval;
 	struct php_pcntl_pending_signal *queue, *next;
+	sigset_t mask;
+	sigset_t old_mask;
 	TSRMLS_FETCH();
 
 	/* Bail if the queue is empty or if we are already playing the queue*/
@@ -1115,8 +1130,6 @@
 	queue = PCNTL_G(head);
 	PCNTL_G(head) = NULL; /* simple stores are atomic */
 	
-	/* Allocate */
-
 	while (queue) {
 		if (zend_hash_index_find(&PCNTL_G(php_signal_table), queue->signo, (void **) &handle)==SUCCESS) {
 			MAKE_STD_ZVAL(retval);
@@ -1131,10 +1144,19 @@
 			zval_ptr_dtor(&retval);
 		}
 
+		/* create a mask of all signals */
+		sigfillset(&mask);
+
+		/* block all signals, storing original signal mask in old_mask, while we modify the linked list */
+		sigprocmask(SIG_BLOCK, &mask, &old_mask);
+
 		next = queue->next;
 		queue->next = PCNTL_G(spares);
 		PCNTL_G(spares) = queue;
 		queue = next;
+
+		/* return signal mask to previous state */
+		sigprocmask(SIG_SETMASK, &old_mask, NULL);
 	}
 
 	/* Re-enable queue */
 
PHP Copyright © 2001-2014 The PHP Group
All rights reserved.
Last updated: Sun Apr 20 13:01:59 2014 UTC