summaryrefslogtreecommitdiff
path: root/Zend
diff options
context:
space:
mode:
authorNikita Popov <nikita.ppv@gmail.com>2019-07-23 10:38:23 +0200
committerNikita Popov <nikita.ppv@gmail.com>2019-07-29 15:17:32 +0200
commit38f1288b6427fc9e2fa2b5ad9912745ded923ee7 (patch)
tree65df8f768367df986838b6dc72dfd7a33ee59c79 /Zend
parent68fd435ba81e0208d30218b0558cccbf76b85e49 (diff)
downloadphp-git-38f1288b6427fc9e2fa2b5ad9912745ded923ee7.tar.gz
Fix Zend signals unblocking
There are a few parts here: * opcache should not be blocking signals while invoking compile_file, otherwise signals may remain blocked on a compile error. While at it, also protect SHM memory during compile_file. * We should deactivate Zend signals at the end of the request, to make sure that we gracefully recover from a missing unblock and signals don't remain blocked forever. * We don't use a critical section in deactivation, because it should not be necessary. Additionally we want to clean up the signal queue, if it is non-empty. * Enable SIGG(check) in debug builds so we notice issues in the future.
Diffstat (limited to 'Zend')
-rw-r--r--Zend/zend_signal.c21
1 files changed, 16 insertions, 5 deletions
diff --git a/Zend/zend_signal.c b/Zend/zend_signal.c
index 1cfab63eee..f43de50b64 100644
--- a/Zend/zend_signal.c
+++ b/Zend/zend_signal.c
@@ -330,13 +330,13 @@ void zend_signal_activate(void)
SIGG(active) = 1;
SIGG(depth) = 0;
+ SIGG(check) = ZEND_DEBUG;
} /* }}} */
/* {{{ zend_signal_deactivate
* */
void zend_signal_deactivate(void)
{
-
if (SIGG(check)) {
size_t x;
struct sigaction sa;
@@ -344,21 +344,32 @@ void zend_signal_deactivate(void)
if (SIGG(depth) != 0) {
zend_error(E_CORE_WARNING, "zend_signal: shutdown with non-zero blocking depth (%d)", SIGG(depth));
}
+
/* did anyone steal our installed handler */
for (x = 0; x < sizeof(zend_sigs) / sizeof(*zend_sigs); x++) {
sigaction(zend_sigs[x], NULL, &sa);
- if (sa.sa_sigaction != zend_signal_handler_defer) {
+ if (sa.sa_sigaction != zend_signal_handler_defer &&
+ sa.sa_sigaction != (void *) SIG_IGN) {
zend_error(E_CORE_WARNING, "zend_signal: handler was replaced for signal (%d) after startup", zend_sigs[x]);
}
}
}
- SIGNAL_BEGIN_CRITICAL();
- SIGG(active) = 0;
+ /* After active=0 is set, signal handlers will be called directly and other
+ * state that is reset below will not be accessed. */
+ *((volatile int *) &SIGG(active)) = 0;
+
SIGG(running) = 0;
SIGG(blocked) = 0;
SIGG(depth) = 0;
- SIGNAL_END_CRITICAL();
+
+ /* If there are any queued signals because of a missed unblock, drop them. */
+ if (SIGG(phead) && SIGG(ptail)) {
+ SIGG(ptail)->next = SIGG(pavail);
+ SIGG(pavail) = SIGG(phead);
+ SIGG(phead) = NULL;
+ SIGG(ptail) = NULL;
+ }
}
/* }}} */