fix: no-op when signal handlers are called on threads not managed by PHP (#9766)

This commit is contained in:
Kévin Dunglas 2022-10-22 11:17:27 +02:00 committed by GitHub
parent 77eadc5c9f
commit 9da75d0c63
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 21 additions and 1 deletions

2
NEWS
View file

@ -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)

View file

@ -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 */

View file

@ -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)

View file

@ -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;

View file

@ -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 */