Skip to content

Commit b09c2f8

Browse files
bp1222nikic
authored andcommitted
Fixed bug #73783
Bug #73783 raises an issue with signal handling when using SIG_IGN. With PHP7.1 ZEND_SIGNALS is defaulted to on, which will for all signals set the handler as zend_signal_handler_defer. This is problematic for syscalls like sleep(), which will only return when the requisite number of seconds have elapsed, or, a non-ignored signal is raised. In this case we want to SIG_IGN SIGCHLD, however, SIG_IGN is only stored in the SIGG(handlers) array, and the actual system level handler is defined. This prevents proper signal ignoring when requeted.
1 parent 7746ed9 commit b09c2f8

File tree

3 files changed

+38
-4
lines changed

3 files changed

+38
-4
lines changed

NEWS

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ PHP NEWS
1111
. Fixed bug #73727 (ZEND_MM_BITSET_LEN is "undefined symbol" in
1212
zend_bitset.h). (Nikita)
1313
. Fixed bug #73753 (unserialized array pointer not advancing). (David Walker)
14+
. Fixed bug #73783 (SIG_IGN doesn't work when Zend Signals is enabled).
15+
(David Walker)
1416

1517
- CLI:
1618
. Fixed bug #72555 (CLI output(japanese) on Windows). (Anatol)

Zend/zend_signal.c

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -198,7 +198,7 @@ static void zend_signal_handler(int signo, siginfo_t *siginfo, void *context)
198198
#endif
199199
}
200200
}
201-
} else if (p_sig.handler != SIG_IGN) { /* ignore SIG_IGN */
201+
} else {
202202
if (p_sig.flags & SA_SIGINFO) {
203203
if (p_sig.flags & SA_RESETHAND) {
204204
SIGG(handlers)[signo-1].flags = 0;
@@ -234,9 +234,13 @@ ZEND_API int zend_sigaction(int signo, const struct sigaction *act, struct sigac
234234
}
235235

236236
memset(&sa, 0, sizeof(sa));
237-
sa.sa_flags = SA_SIGINFO | (act->sa_flags & SA_FLAGS_MASK);
238-
sa.sa_sigaction = zend_signal_handler_defer;
239-
sa.sa_mask = global_sigmask;
237+
if (SIGG(handlers)[signo-1].handler == (void *) SIG_IGN) {
238+
sa.sa_sigaction = (void *) SIG_IGN;
239+
} else {
240+
sa.sa_flags = SA_SIGINFO | (act->sa_flags & SA_FLAGS_MASK);
241+
sa.sa_sigaction = zend_signal_handler_defer;
242+
sa.sa_mask = global_sigmask;
243+
}
240244

241245
if (sigaction(signo, &sa, NULL) < 0) {
242246
zend_error_noreturn(E_ERROR, "Error installing signal handler for %d", signo);

ext/pcntl/tests/bug73783.phpt

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
--TEST--
2+
Bug #73783: (SIG_IGN needs to be set to prevent syscals from returning early)
3+
--SKIPIF--
4+
<?php
5+
if (!extension_loaded('pcntl')) die('skip pcntl extension not available');
6+
elseif (!extension_loaded('posix')) die('skip posix extension not available');
7+
?>
8+
--FILE--
9+
<?php
10+
pcntl_signal(SIGCHLD, SIG_IGN);
11+
12+
switch(pcntl_fork()) {
13+
case 0:
14+
exit;
15+
break;
16+
}
17+
18+
$before = microtime(true);
19+
sleep(1);
20+
21+
if (microtime(true) - $before >= 0.8) {
22+
echo "working\n";
23+
} else {
24+
echo "failed\n";
25+
}
26+
?>
27+
--EXPECTF--
28+
working

0 commit comments

Comments
 (0)