From: David Walker Date: Mon, 19 Dec 2016 21:29:18 +0000 (-0700) Subject: Fixed bug #73783 X-Git-Tag: php-7.1.1RC1~48 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=b09c2f899ebc14029d0936d770cced10b607f84b;p=php 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. --- diff --git a/NEWS b/NEWS index 05492132b9..9d1a2c5bc9 100644 --- a/NEWS +++ b/NEWS @@ -11,6 +11,8 @@ PHP NEWS . Fixed bug #73727 (ZEND_MM_BITSET_LEN is "undefined symbol" in zend_bitset.h). (Nikita) . Fixed bug #73753 (unserialized array pointer not advancing). (David Walker) + . Fixed bug #73783 (SIG_IGN doesn't work when Zend Signals is enabled). + (David Walker) - CLI: . Fixed bug #72555 (CLI output(japanese) on Windows). (Anatol) diff --git a/Zend/zend_signal.c b/Zend/zend_signal.c index 1d8baaf0f5..605187aed2 100644 --- a/Zend/zend_signal.c +++ b/Zend/zend_signal.c @@ -198,7 +198,7 @@ static void zend_signal_handler(int signo, siginfo_t *siginfo, void *context) #endif } } - } else if (p_sig.handler != SIG_IGN) { /* ignore SIG_IGN */ + } else { if (p_sig.flags & SA_SIGINFO) { if (p_sig.flags & SA_RESETHAND) { SIGG(handlers)[signo-1].flags = 0; @@ -234,9 +234,13 @@ ZEND_API int zend_sigaction(int signo, const struct sigaction *act, struct sigac } memset(&sa, 0, sizeof(sa)); - sa.sa_flags = SA_SIGINFO | (act->sa_flags & SA_FLAGS_MASK); - sa.sa_sigaction = zend_signal_handler_defer; - sa.sa_mask = global_sigmask; + if (SIGG(handlers)[signo-1].handler == (void *) SIG_IGN) { + sa.sa_sigaction = (void *) SIG_IGN; + } else { + sa.sa_flags = SA_SIGINFO | (act->sa_flags & SA_FLAGS_MASK); + sa.sa_sigaction = zend_signal_handler_defer; + sa.sa_mask = global_sigmask; + } if (sigaction(signo, &sa, NULL) < 0) { zend_error_noreturn(E_ERROR, "Error installing signal handler for %d", signo); diff --git a/ext/pcntl/tests/bug73783.phpt b/ext/pcntl/tests/bug73783.phpt new file mode 100644 index 0000000000..beacdf6b8d --- /dev/null +++ b/ext/pcntl/tests/bug73783.phpt @@ -0,0 +1,28 @@ +--TEST-- +Bug #73783: (SIG_IGN needs to be set to prevent syscals from returning early) +--SKIPIF-- + +--FILE-- += 0.8) { + echo "working\n"; +} else { + echo "failed\n"; +} +?> +--EXPECTF-- +working