From 9da75d0c6376a683cef6a58013c1ecafb68fa9c1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?K=C3=A9vin=20Dunglas?= Date: Sat, 22 Oct 2022 11:17:27 +0200 Subject: [PATCH] fix: no-op when signal handlers are called on threads not managed by PHP (#9766) --- NEWS | 2 ++ TSRM/TSRM.c | 5 +++++ TSRM/TSRM.h | 1 + Zend/zend_execute_API.c | 8 +++++++- Zend/zend_signal.c | 6 ++++++ 5 files changed, 21 insertions(+), 1 deletion(-) diff --git a/NEWS b/NEWS index 355ae1d5b8d..c8ded9b6051 100644 --- a/NEWS +++ b/NEWS @@ -12,6 +12,8 @@ PHP NEWS . SA_ONSTACK is now set for signal handlers to be friendlier to other in-process code such as Go's cgo. (Kévin Dunglas) . SA_ONSTACK is now set when signals are disabled. (Kévin Dunglas) + . Fix GH-9649: Signal handlers now do a no-op instead of crashing when + executed on threads not managed by TSRM. (Kévin Dunglas) - Fileinfo: . Upgrade bundled libmagic to 5.43. (Anatol) diff --git a/TSRM/TSRM.c b/TSRM/TSRM.c index 0c6daedf399..76ffe3fb337 100644 --- a/TSRM/TSRM.c +++ b/TSRM/TSRM.c @@ -779,4 +779,9 @@ TSRM_API const char *tsrm_api_name(void) #endif }/*}}}*/ +TSRM_API bool tsrm_is_managed_thread() +{/*{{{*/ + return tsrm_tls_get() ? true : false; +}/*}}}*/ + #endif /* ZTS */ diff --git a/TSRM/TSRM.h b/TSRM/TSRM.h index 60b65ca8ec7..3bb32e4da28 100644 --- a/TSRM/TSRM.h +++ b/TSRM/TSRM.h @@ -137,6 +137,7 @@ TSRM_API size_t tsrm_get_ls_cache_tcb_offset(void); TSRM_API bool tsrm_is_main_thread(void); TSRM_API bool tsrm_is_shutdown(void); TSRM_API const char *tsrm_api_name(void); +TSRM_API bool tsrm_is_managed_thread(void); #ifdef TSRM_WIN32 # define TSRM_TLS __declspec(thread) diff --git a/Zend/zend_execute_API.c b/Zend/zend_execute_API.c index c7ccfc5a91c..235a8fe8a79 100644 --- a/Zend/zend_execute_API.c +++ b/Zend/zend_execute_API.c @@ -1355,7 +1355,13 @@ ZEND_API ZEND_NORETURN void ZEND_FASTCALL zend_timeout(void) /* {{{ */ #ifndef ZEND_WIN32 static void zend_timeout_handler(int dummy) /* {{{ */ { -#ifndef ZTS +#ifdef ZTS + if (!tsrm_is_managed_thread()) { + fprintf(stderr, "zend_timeout_handler() called in a thread not managed by PHP. The expected signal handler will not be called. This is probably a bug.\n"); + + return; + } +#else if (zend_atomic_bool_load_ex(&EG(timed_out))) { /* Die on hard timeout */ const char *error_filename = NULL; diff --git a/Zend/zend_signal.c b/Zend/zend_signal.c index be48a91d3d8..fc913b72f06 100644 --- a/Zend/zend_signal.c +++ b/Zend/zend_signal.c @@ -87,6 +87,12 @@ void zend_signal_handler_defer(int signo, siginfo_t *siginfo, void *context) zend_signal_queue_t *queue, *qtmp; #ifdef ZTS + if (!tsrm_is_managed_thread()) { + fprintf(stderr, "zend_signal_handler_defer() called in a thread not managed by PHP. The expected signal handler will not be called. This is probably a bug.\n"); + + return; + } + /* A signal could hit after TSRM shutdown, in this case globals are already freed. */ if (tsrm_is_shutdown()) { /* Forward to default handler handler */