Skip to content

Commit f7be15d

Browse files
committed
Revert the fix for GH-11498
People relied on manually waiting for children, but the fix for GH-11498 broke this. Fixing this in PHP is fundamentally incompatible with doing the wait loop in userland. This reverts to the old behaviour. Closes GH-11863.
1 parent 162bd2a commit f7be15d

File tree

3 files changed

+17
-53
lines changed

3 files changed

+17
-53
lines changed

NEWS

+4
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,10 @@ PHP NEWS
3434
. Avoid adding an unnecessary read-lock when loading script from shm if
3535
restart is in progress. (mikhainin)
3636

37+
- PCNTL:
38+
. Revert behaviour of receiving SIGCHLD signals back to the behaviour
39+
before 8.1.22. (nielsdos)
40+
3741
- Standard:
3842
. Prevent int overflow on $decimals in number_format. (Marc Bennewitz)
3943

ext/pcntl/pcntl.c

+8-50
Original file line numberDiff line numberDiff line change
@@ -1338,68 +1338,26 @@ static void pcntl_signal_handler(int signo, siginfo_t *siginfo, void *context)
13381338
static void pcntl_signal_handler(int signo)
13391339
#endif
13401340
{
1341-
struct php_pcntl_pending_signal *psig_first = PCNTL_G(spares);
1342-
if (!psig_first) {
1341+
struct php_pcntl_pending_signal *psig = PCNTL_G(spares);
1342+
if (!psig) {
13431343
/* oops, too many signals for us to track, so we'll forget about this one */
13441344
return;
13451345
}
1346+
PCNTL_G(spares) = psig->next;
13461347

1347-
struct php_pcntl_pending_signal *psig = NULL;
1348-
1349-
/* Standard signals may be merged into a single one.
1350-
* POSIX specifies that SIGCHLD has the si_pid field (https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/signal.h.html),
1351-
* so we'll handle the merging for that signal.
1352-
* See also: https://www.gnu.org/software/libc/manual/html_node/Merged-Signals.html */
1353-
if (signo == SIGCHLD) {
1354-
/* Note: The first waitpid result is not necessarily the pid that was passed above!
1355-
* We therefore cannot avoid the first waitpid() call. */
1356-
int status;
1357-
pid_t pid;
1358-
while (true) {
1359-
do {
1360-
errno = 0;
1361-
/* Although Linux specifies that WNOHANG will never result in EINTR, POSIX doesn't say so:
1362-
* https://pubs.opengroup.org/onlinepubs/9699919799/functions/waitpid.html */
1363-
pid = waitpid(-1, &status, WNOHANG | WUNTRACED);
1364-
} while (pid <= 0 && errno == EINTR);
1365-
if (pid <= 0) {
1366-
if (UNEXPECTED(!psig)) {
1367-
/* The child might've been consumed by another thread and will be handled there. */
1368-
return;
1369-
}
1370-
break;
1371-
}
1372-
1373-
psig = psig ? psig->next : psig_first;
1374-
psig->signo = signo;
1375-
1376-
#ifdef HAVE_STRUCT_SIGINFO_T
1377-
psig->siginfo = *siginfo;
1378-
psig->siginfo.si_pid = pid;
1379-
#endif
1380-
1381-
if (UNEXPECTED(!psig->next)) {
1382-
break;
1383-
}
1384-
}
1385-
} else {
1386-
psig = psig_first;
1387-
psig->signo = signo;
1348+
psig->signo = signo;
1349+
psig->next = NULL;
13881350

13891351
#ifdef HAVE_STRUCT_SIGINFO_T
1390-
psig->siginfo = *siginfo;
1352+
psig->siginfo = *siginfo;
13911353
#endif
1392-
}
1393-
1394-
PCNTL_G(spares) = psig->next;
1395-
psig->next = NULL;
13961354

13971355
/* the head check is important, as the tick handler cannot atomically clear both
13981356
* the head and tail */
13991357
if (PCNTL_G(head) && PCNTL_G(tail)) {
1400-
PCNTL_G(tail)->next = psig_first;
1358+
PCNTL_G(tail)->next = psig;
14011359
} else {
1402-
PCNTL_G(head) = psig_first;
1360+
PCNTL_G(head) = psig;
14031361
}
14041362
PCNTL_G(tail) = psig;
14051363
PCNTL_G(pending_signals) = 1;

ext/pcntl/tests/gh11498.phpt renamed to ext/pcntl/tests/waiting_on_sigchild_pcntl_wait.phpt

+5-3
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
--TEST--
2-
GH-11498 (SIGCHLD is not always returned from proc_open)
2+
Waiting on SIGCHLD with a pcntl_wait() loop
33
--EXTENSIONS--
44
pcntl
55
--SKIPIF--
@@ -14,8 +14,10 @@ $processes = [];
1414

1515
pcntl_async_signals(true);
1616
pcntl_signal(SIGCHLD, function($sig, $info) use (&$processes) {
17-
echo "SIGCHLD\n";
18-
unset($processes[$info['pid']]);
17+
while (($pid = pcntl_wait($status, WUNTRACED | WNOHANG)) > 0) {
18+
echo "SIGCHLD\n";
19+
unset($processes[$pid]);
20+
}
1921
}, false);
2022

2123
for ($i = 0; $i <= 5; $i++) {

0 commit comments

Comments
 (0)