]> granicus.if.org Git - php/commitdiff
fixed bug #52784 (Race condition when handling many
authorArnaud Le Blanc <lbarnaud@php.net>
Mon, 1 Nov 2010 22:29:25 +0000 (22:29 +0000)
committerArnaud Le Blanc <lbarnaud@php.net>
Mon, 1 Nov 2010 22:29:25 +0000 (22:29 +0000)
concurrent signals)

ext/pcntl/pcntl.c
ext/pcntl/php_signal.c
ext/pcntl/php_signal.h

index 7c5dc0ea06788e8e326df442f3542d624ece2ca0..de5b99e9b681fd050351adc94d8cfc5a7b12b3bd 100755 (executable)
@@ -887,7 +887,7 @@ PHP_FUNCTION(pcntl_signal)
        zend_hash_index_update(&PCNTL_G(php_signal_table), signo, (void **) &handle, sizeof(zval *), (void **) &dest_handle);
        if (dest_handle) zval_add_ref(dest_handle);
        
-       if (php_signal(signo, pcntl_signal_handler, (int) restart_syscalls) == SIG_ERR) {
+       if (php_signal4(signo, pcntl_signal_handler, (int) restart_syscalls, 1) == SIG_ERR) {
                PCNTL_G(last_error) = errno;
                php_error_docref(NULL TSRMLS_CC, E_WARNING, "Error assigning signal");
                RETURN_FALSE;
@@ -1224,7 +1224,13 @@ void pcntl_signal_dispatch()
 {
        zval *param, **handle, *retval;
        struct php_pcntl_pending_signal *queue, *next;
+       sigset_t mask;
+       sigset_t old_mask;
        TSRMLS_FETCH();
+               
+       /* Mask all signals */
+       sigfillset(&mask);
+       sigprocmask(SIG_BLOCK, &mask, &old_mask);
 
        /* Bail if the queue is empty or if we are already playing the queue*/
        if (! PCNTL_G(head) || PCNTL_G(processing_signal_queue))
@@ -1260,6 +1266,9 @@ void pcntl_signal_dispatch()
 
        /* Re-enable queue */
        PCNTL_G(processing_signal_queue) = 0;
+       
+       /* return signal mask to previous state */
+       sigprocmask(SIG_SETMASK, &old_mask, NULL);
 }
 
 
index 6963e6ff379dde39f56ba67e4de1dbabd558e2b4..d3f86d0f1225484044c9c3d7c8d5aab9a4e53a62 100644 (file)
 
 /* php_signal using sigaction is derrived from Advanced Programing
  * in the Unix Environment by W. Richard Stevens p 298. */
-Sigfunc *php_signal(int signo, Sigfunc *func, int restart)
+Sigfunc *php_signal4(int signo, Sigfunc *func, int restart, int mask_all)
 {
        struct sigaction act,oact;
        act.sa_handler = func;
-       sigemptyset(&act.sa_mask);
+       if (mask_all) {
+               sigfillset(&act.sa_mask);
+       } else {
+               sigemptyset(&act.sa_mask);
+       }
        act.sa_flags = 0;
        if (signo == SIGALRM || (! restart)) {
 #ifdef SA_INTERRUPT
@@ -43,6 +47,11 @@ Sigfunc *php_signal(int signo, Sigfunc *func, int restart)
        return oact.sa_handler;
 }
 
+Sigfunc *php_signal(int signo, Sigfunc *func, int restart)
+{
+       return php_signal4(signo, func, restart, 0);
+}
+
 /*
  * Local variables:
  * tab-width: 4
index f9e7a5af15e659a734ec526838767cc1ef14abea..cb9a1a767c5a1a8e657c8e117976b73c6b631704 100644 (file)
@@ -31,5 +31,6 @@
 
 typedef void Sigfunc(int);
 Sigfunc *php_signal(int signo, Sigfunc *func, int restart);
+Sigfunc *php_signal4(int signo, Sigfunc *func, int restart, int mask_all);
 
 #endif