diff --git a/NEWS b/NEWS index 355ae1d5b8d91..c8ded9b60515d 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 0c6daedf399c8..76ffe3fb3376f 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 60b65ca8ec762..3bb32e4da289a 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 c7ccfc5a91ccc..235a8fe8a79cc 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 be48a91d3d88b..fc913b72f0641 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 */