Skip to content

Commit 3ac257f

Browse files
committed
MFH fixed bug #52784 (Race condition when handling many
concurrent signals)
1 parent cd63986 commit 3ac257f

File tree

4 files changed

+27
-4
lines changed

4 files changed

+27
-4
lines changed

NEWS

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,8 @@
8888
(CURLOPT_STDERR)). (Gustavo)
8989
- Fixed bug #52786 (PHP should reset section to [PHP] after ini sections).
9090
(Fedora at famillecollet dot com)
91+
- Fixed bug #52784 (Race condition when handling many concurrent signals).
92+
(nick dot telford at gmail dot com, Arnaud)
9193
- Fixed bug #52772 (var_dump() doesn't check for the existence of
9294
get_class_name before calling it). (Kalle, Gustavo)
9395
- Fixed bug #52744 (cal_days_in_month incorrect for December 1 BCE).

ext/pcntl/pcntl.c

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -887,7 +887,7 @@ PHP_FUNCTION(pcntl_signal)
887887
zend_hash_index_update(&PCNTL_G(php_signal_table), signo, (void **) &handle, sizeof(zval *), (void **) &dest_handle);
888888
if (dest_handle) zval_add_ref(dest_handle);
889889

890-
if (php_signal(signo, pcntl_signal_handler, (int) restart_syscalls) == SIG_ERR) {
890+
if (php_signal4(signo, pcntl_signal_handler, (int) restart_syscalls, 1) == SIG_ERR) {
891891
PCNTL_G(last_error) = errno;
892892
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Error assigning signal");
893893
RETURN_FALSE;
@@ -1224,11 +1224,19 @@ void pcntl_signal_dispatch()
12241224
{
12251225
zval *param, **handle, *retval;
12261226
struct php_pcntl_pending_signal *queue, *next;
1227+
sigset_t mask;
1228+
sigset_t old_mask;
12271229
TSRMLS_FETCH();
1230+
1231+
/* Mask all signals */
1232+
sigfillset(&mask);
1233+
sigprocmask(SIG_BLOCK, &mask, &old_mask);
12281234

12291235
/* Bail if the queue is empty or if we are already playing the queue*/
1230-
if (! PCNTL_G(head) || PCNTL_G(processing_signal_queue))
1236+
if (! PCNTL_G(head) || PCNTL_G(processing_signal_queue)) {
1237+
sigprocmask(SIG_SETMASK, &old_mask, NULL);
12311238
return;
1239+
}
12321240

12331241
/* Prevent reentrant handler calls */
12341242
PCNTL_G(processing_signal_queue) = 1;
@@ -1260,6 +1268,9 @@ void pcntl_signal_dispatch()
12601268

12611269
/* Re-enable queue */
12621270
PCNTL_G(processing_signal_queue) = 0;
1271+
1272+
/* return signal mask to previous state */
1273+
sigprocmask(SIG_SETMASK, &old_mask, NULL);
12631274
}
12641275

12651276

ext/pcntl/php_signal.c

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,11 +22,15 @@
2222

2323
/* php_signal using sigaction is derrived from Advanced Programing
2424
* in the Unix Environment by W. Richard Stevens p 298. */
25-
Sigfunc *php_signal(int signo, Sigfunc *func, int restart)
25+
Sigfunc *php_signal4(int signo, Sigfunc *func, int restart, int mask_all)
2626
{
2727
struct sigaction act,oact;
2828
act.sa_handler = func;
29-
sigemptyset(&act.sa_mask);
29+
if (mask_all) {
30+
sigfillset(&act.sa_mask);
31+
} else {
32+
sigemptyset(&act.sa_mask);
33+
}
3034
act.sa_flags = 0;
3135
if (signo == SIGALRM || (! restart)) {
3236
#ifdef SA_INTERRUPT
@@ -43,6 +47,11 @@ Sigfunc *php_signal(int signo, Sigfunc *func, int restart)
4347
return oact.sa_handler;
4448
}
4549

50+
Sigfunc *php_signal(int signo, Sigfunc *func, int restart)
51+
{
52+
return php_signal4(signo, func, restart, 0);
53+
}
54+
4655
/*
4756
* Local variables:
4857
* tab-width: 4

ext/pcntl/php_signal.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,5 +31,6 @@
3131

3232
typedef void Sigfunc(int);
3333
Sigfunc *php_signal(int signo, Sigfunc *func, int restart);
34+
Sigfunc *php_signal4(int signo, Sigfunc *func, int restart, int mask_all);
3435

3536
#endif

0 commit comments

Comments
 (0)