summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorArnaud Le Blanc <lbarnaud@php.net>2011-02-14 17:06:31 +0000
committerArnaud Le Blanc <lbarnaud@php.net>2011-02-14 17:06:31 +0000
commitc97f651b03131252da83eb46c447b3a4e7461eeb (patch)
tree6329dd2edaa0cf6957fcc73a7b865b31df96a792
parentc9a37f78983aee253b764528ba7733e55cd25f40 (diff)
downloadphp-git-c97f651b03131252da83eb46c447b3a4e7461eeb.tar.gz
MFH fixed bug #52784 (Race condition when handling many
concurrent signals)
-rwxr-xr-xext/pcntl/pcntl.c15
-rw-r--r--ext/pcntl/php_signal.c13
-rw-r--r--ext/pcntl/php_signal.h1
3 files changed, 24 insertions, 5 deletions
diff --git a/ext/pcntl/pcntl.c b/ext/pcntl/pcntl.c
index 77742b3d5b..70b393bb22 100755
--- a/ext/pcntl/pcntl.c
+++ b/ext/pcntl/pcntl.c
@@ -567,7 +567,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) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Error assigning signal");
RETURN_FALSE;
}
@@ -682,11 +682,19 @@ void pcntl_tick_handler()
{
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))
+ if (! PCNTL_G(head) || PCNTL_G(processing_signal_queue)) {
+ sigprocmask(SIG_SETMASK, &old_mask, NULL);
return;
+ }
/* Prevent reentrant handler calls */
PCNTL_G(processing_signal_queue) = 1;
@@ -718,6 +726,9 @@ void pcntl_tick_handler()
/* Re-enable queue */
PCNTL_G(processing_signal_queue) = 0;
+
+ /* return signal mask to previous state */
+ sigprocmask(SIG_SETMASK, &old_mask, NULL);
}
diff --git a/ext/pcntl/php_signal.c b/ext/pcntl/php_signal.c
index 99544c81ff..57a1301ece 100644
--- a/ext/pcntl/php_signal.c
+++ b/ext/pcntl/php_signal.c
@@ -22,12 +22,15 @@
/* 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
@@ -44,3 +47,7 @@ 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);
+}
diff --git a/ext/pcntl/php_signal.h b/ext/pcntl/php_signal.h
index 2cd7537ec9..fd6bd09558 100644
--- a/ext/pcntl/php_signal.h
+++ b/ext/pcntl/php_signal.h
@@ -24,5 +24,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