Skip to content

Commit

Permalink
MFH fixed bug #52784 (Race condition when handling many
Browse files Browse the repository at this point in the history
concurrent signals)
  • Loading branch information
arnaud-lb committed Feb 14, 2011
1 parent c9a37f7 commit c97f651
Show file tree
Hide file tree
Showing 3 changed files with 24 additions and 5 deletions.
15 changes: 13 additions & 2 deletions ext/pcntl/pcntl.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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);
}


Expand Down
13 changes: 10 additions & 3 deletions ext/pcntl/php_signal.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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);
}
1 change: 1 addition & 0 deletions ext/pcntl/php_signal.h
Original file line number Diff line number Diff line change
Expand Up @@ -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

0 comments on commit c97f651

Please sign in to comment.