Skip to content

Commit 296fad1

Browse files
committed
ext/pcntl: fix pcntl_signal_dispatch() stale tail pointer and exception handling.
close GH-21259
1 parent db6cca2 commit 296fad1

File tree

3 files changed

+48
-0
lines changed

3 files changed

+48
-0
lines changed

NEWS

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,8 @@ PHP NEWS
5050
on NetBSD/Solaris platforms. (David Carlier)
5151
. Fixed pcntl_signal() signal table registering the callback first
5252
OS-wise before the internal list. (David Carlier)
53+
. Fixed pcntl_signal_dispatch() stale pointer and exception
54+
handling. (David Carlier)
5355

5456
- PDO_PGSQL:
5557
. Fixed bug GH-21055 (connection attribute status typo for GSS negotiation).

ext/pcntl/pcntl.c

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1343,6 +1343,7 @@ void pcntl_signal_dispatch(void)
13431343

13441344
queue = PCNTL_G(head);
13451345
PCNTL_G(head) = NULL; /* simple stores are atomic */
1346+
PCNTL_G(tail) = NULL;
13461347

13471348
/* Allocate */
13481349
while (queue) {
@@ -1364,6 +1365,9 @@ void pcntl_signal_dispatch(void)
13641365
#ifdef HAVE_STRUCT_SIGINFO_T
13651366
zval_ptr_dtor(&params[1]);
13661367
#endif
1368+
if (EG(exception)) {
1369+
break;
1370+
}
13671371
}
13681372
}
13691373

@@ -1373,6 +1377,14 @@ void pcntl_signal_dispatch(void)
13731377
queue = next;
13741378
}
13751379

1380+
/* drain the remaining in case of exception thrown */
1381+
while (queue) {
1382+
next = queue->next;
1383+
queue->next = PCNTL_G(spares);
1384+
PCNTL_G(spares) = queue;
1385+
queue = next;
1386+
}
1387+
13761388
PCNTL_G(pending_signals) = 0;
13771389

13781390
/* Re-enable queue */
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
--TEST--
2+
pcntl_signal_dispatch() stops dispatching after handler throws exception
3+
--EXTENSIONS--
4+
pcntl
5+
posix
6+
--FILE--
7+
<?php
8+
9+
$called = [];
10+
11+
pcntl_signal(SIGUSR1, function ($signo) use (&$called) {
12+
$called[] = 'SIGUSR1';
13+
throw new \Exception('Exception in signal handler');
14+
});
15+
16+
pcntl_signal(SIGUSR2, function ($signo) use (&$called) {
17+
$called[] = 'SIGUSR2';
18+
});
19+
20+
posix_kill(posix_getpid(), SIGUSR1);
21+
posix_kill(posix_getpid(), SIGUSR2);
22+
23+
try {
24+
pcntl_signal_dispatch();
25+
} catch (\Exception $e) {
26+
echo $e->getMessage() . "\n";
27+
}
28+
29+
echo "Handlers called: " . implode(', ', $called) . "\n";
30+
31+
?>
32+
--EXPECT--
33+
Exception in signal handler
34+
Handlers called: SIGUSR1

0 commit comments

Comments
 (0)