fixed bug #52784 (Race condition when handling many

concurrent signals)
This commit is contained in:
Arnaud Le Blanc 2010-11-01 22:29:25 +00:00
parent a9507474e3
commit 61e7730ee8
3 changed files with 22 additions and 3 deletions

View File

@ -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);
}

View File

@ -22,11 +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
@ -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

View 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