From 68485f8ab4df0e1b3e4f446006ce25b6be358975 Mon Sep 17 00:00:00 2001 From: Joe Watkins Date: Wed, 26 Jun 2019 13:18:50 +0200 Subject: implement tsrm_is_shutdown API --- TSRM/TSRM.c | 119 +++++++++++++++++++-------------------------------- TSRM/TSRM.h | 4 +- Zend/zend_signal.c | 11 ++--- main/main.c | 4 -- sapi/phpdbg/phpdbg.c | 4 +- 5 files changed, 52 insertions(+), 90 deletions(-) diff --git a/TSRM/TSRM.c b/TSRM/TSRM.c index 34080eed96..1a8d5192ff 100644 --- a/TSRM/TSRM.c +++ b/TSRM/TSRM.c @@ -17,6 +17,13 @@ #include #include +#ifdef ZEND_DEBUG +# include +# define TSRM_ASSERT assert +#else +# define TSRM_ASSERT +#endif + typedef struct _tsrm_tls_entry tsrm_tls_entry; /* TSRMLS_CACHE_DEFINE; is already done in Zend, this is being always compiled statically. */ @@ -123,6 +130,7 @@ static DWORD tls_key; #endif TSRM_TLS uint8_t in_main_thread = 0; +TSRM_TLS uint8_t is_thread_shutdown = 0; /* Startup TSRM (call once for the entire process) */ TSRM_API int tsrm_startup(int expected_threads, int expected_resources, int debug_level, char *debug_filename) @@ -141,6 +149,7 @@ TSRM_API int tsrm_startup(int expected_threads, int expected_resources, int debu /* ensure singleton */ in_main_thread = 1; + is_thread_shutdown = 0; tsrm_error_file = stderr; tsrm_error_set(debug_level, debug_filename); @@ -149,6 +158,7 @@ TSRM_API int tsrm_startup(int expected_threads, int expected_resources, int debu tsrm_tls_table = (tsrm_tls_entry **) calloc(tsrm_tls_table_size, sizeof(tsrm_tls_entry *)); if (!tsrm_tls_table) { TSRM_ERROR((TSRM_ERROR_LEVEL_ERROR, "Unable to allocate TLS table")); + is_thread_shutdown = 1; return 0; } id_count=0; @@ -157,8 +167,8 @@ TSRM_API int tsrm_startup(int expected_threads, int expected_resources, int debu resource_types_table = (tsrm_resource_type *) calloc(resource_types_table_size, sizeof(tsrm_resource_type)); if (!resource_types_table) { TSRM_ERROR((TSRM_ERROR_LEVEL_ERROR, "Unable to allocate resource types table")); + is_thread_shutdown = 1; free(tsrm_tls_table); - tsrm_tls_table = NULL; return 0; } @@ -180,45 +190,44 @@ TSRM_API void tsrm_shutdown(void) {/*{{{*/ int i; + if (is_thread_shutdown) { + /* shutdown must only occur once */ + return; + } + + is_thread_shutdown = 1; + if (!in_main_thread) { - /* ensure singleton */ + /* only the main thread may shutdown tsrm */ return; } - if (tsrm_tls_table) { - for (i=0; inext; - for (j=0; jcount; j++) { - if (p->storage[j]) { - if (resource_types_table && !resource_types_table[j].done && resource_types_table[j].dtor) { - resource_types_table[j].dtor(p->storage[j]); - } - if (!resource_types_table[j].fast_offset) { - free(p->storage[j]); - } + next_p = p->next; + for (j=0; jcount; j++) { + if (p->storage[j]) { + if (resource_types_table && !resource_types_table[j].done && resource_types_table[j].dtor) { + resource_types_table[j].dtor(p->storage[j]); + } + if (!resource_types_table[j].fast_offset) { + free(p->storage[j]); } } - free(p->storage); - free(p); - p = next_p; } + free(p->storage); + free(p); + p = next_p; } - free(tsrm_tls_table); - tsrm_tls_table = NULL; - } - if (resource_types_table) { - free(resource_types_table); - resource_types_table=NULL; } + free(tsrm_tls_table); + free(resource_types_table); tsrm_mutex_free(tsmm_mutex); - tsmm_mutex = NULL; tsrm_mutex_free(tsrm_env_mutex); - tsrm_env_mutex = NULL; TSRM_ERROR((TSRM_ERROR_LEVEL_CORE, "Shutdown TSRM")); if (tsrm_error_file!=stderr) { fclose(tsrm_error_file); @@ -556,6 +565,8 @@ void ts_free_thread(void) int hash_value; tsrm_tls_entry *last=NULL; + TSRM_ASSERT(!in_main_thread); + tsrm_mutex_lock(tsmm_mutex); hash_value = THREAD_HASH_OF(thread_id, tsrm_tls_table_size); thread_resources = tsrm_tls_table[hash_value]; @@ -590,55 +601,6 @@ void ts_free_thread(void) tsrm_mutex_unlock(tsmm_mutex); }/*}}}*/ - -/* frees all resources allocated for all threads except current */ -void ts_free_worker_threads(void) -{/*{{{*/ - tsrm_tls_entry *thread_resources; - int i; - THREAD_T thread_id = tsrm_thread_id(); - int hash_value; - tsrm_tls_entry *last=NULL; - - tsrm_mutex_lock(tsmm_mutex); - hash_value = THREAD_HASH_OF(thread_id, tsrm_tls_table_size); - thread_resources = tsrm_tls_table[hash_value]; - - while (thread_resources) { - if (thread_resources->thread_id != thread_id) { - for (i=0; icount; i++) { - if (resource_types_table[i].dtor) { - resource_types_table[i].dtor(thread_resources->storage[i]); - } - } - for (i=0; icount; i++) { - if (!resource_types_table[i].fast_offset) { - free(thread_resources->storage[i]); - } - } - free(thread_resources->storage); - if (last) { - last->next = thread_resources->next; - } else { - tsrm_tls_table[hash_value] = thread_resources->next; - } - free(thread_resources); - if (last) { - thread_resources = last->next; - } else { - thread_resources = tsrm_tls_table[hash_value]; - } - } else { - if (thread_resources->next) { - last = thread_resources; - } - thread_resources = thread_resources->next; - } - } - tsrm_mutex_unlock(tsmm_mutex); -}/*}}}*/ - - /* deallocates all occurrences of a given id */ void ts_free_id(ts_rsrc_id id) {/*{{{*/ @@ -885,6 +847,11 @@ TSRM_API uint8_t tsrm_is_main_thread(void) return in_main_thread; }/*}}}*/ +TSRM_API uint8_t tsrm_is_shutdown(void) +{/*{{{*/ + return is_thread_shutdown; +}/*}}}*/ + TSRM_API const char *tsrm_api_name(void) {/*{{{*/ #if defined(GNUPTH) diff --git a/TSRM/TSRM.h b/TSRM/TSRM.h index d2be318440..3c88ac3edb 100644 --- a/TSRM/TSRM.h +++ b/TSRM/TSRM.h @@ -115,9 +115,6 @@ TSRM_API void *ts_resource_ex(ts_rsrc_id id, THREAD_T *th_id); /* frees all resources allocated for the current thread */ TSRM_API void ts_free_thread(void); -/* frees all resources allocated for all threads except current */ -void ts_free_worker_threads(void); - /* deallocates all occurrences of a given id */ TSRM_API void ts_free_id(ts_rsrc_id id); @@ -157,6 +154,7 @@ TSRM_API void tsrm_free_interpreter_context(void *context); TSRM_API void *tsrm_get_ls_cache(void); TSRM_API uint8_t tsrm_is_main_thread(void); +TSRM_API uint8_t tsrm_is_shutdown(void); TSRM_API const char *tsrm_api_name(void); #ifdef TSRM_WIN32 diff --git a/Zend/zend_signal.c b/Zend/zend_signal.c index 3e9fd227ac..703097eeb5 100644 --- a/Zend/zend_signal.c +++ b/Zend/zend_signal.c @@ -82,16 +82,17 @@ void zend_signal_handler_defer(int signo, siginfo_t *siginfo, void *context) { int errno_save = errno; zend_signal_queue_t *queue, *qtmp; - zend_bool is_handling_safe = 1; #ifdef ZTS /* A signal could hit after TSRM shutdown, in this case globals are already freed. */ - if (NULL == TSRMLS_CACHE || NULL == TSRMG_BULK_STATIC(zend_signal_globals_id, zend_signal_globals_t *)) { - is_handling_safe = 0; + if (tsrm_is_shutdown()) { + /* Forward to default handler handler */ + zend_signal_handler(signo, siginfo, context); + return; } #endif - if (EXPECTED(is_handling_safe && SIGG(active))) { + if (EXPECTED(SIGG(active))) { if (UNEXPECTED(SIGG(depth) == 0)) { /* try to handle signal */ if (UNEXPECTED(SIGG(blocked))) { SIGG(blocked) = 0; @@ -176,7 +177,7 @@ static void zend_signal_handler(int signo, siginfo_t *siginfo, void *context) sigset_t sigset; zend_signal_entry_t p_sig; #ifdef ZTS - if (NULL == TSRMLS_CACHE || NULL == TSRMG_BULK_STATIC(zend_signal_globals_id, zend_signal_globals_t *)) { + if (tsrm_is_shutdown()) { p_sig.flags = 0; p_sig.handler = SIG_DFL; } else diff --git a/main/main.c b/main/main.c index f87d07a192..d276528edb 100644 --- a/main/main.c +++ b/main/main.c @@ -2514,10 +2514,6 @@ void php_module_shutdown(void) zend_interned_strings_switch_storage(0); -#ifdef ZTS - ts_free_worker_threads(); -#endif - #if ZEND_RC_DEBUG zend_rc_debug = 0; #endif diff --git a/sapi/phpdbg/phpdbg.c b/sapi/phpdbg/phpdbg.c index eca24b4a4d..463749ea3a 100644 --- a/sapi/phpdbg/phpdbg.c +++ b/sapi/phpdbg/phpdbg.c @@ -2161,8 +2161,6 @@ phpdbg_out: Z_PTR_P(zv) = (void*)PHPDBG_G(orig_url_wrap_php); } - php_module_shutdown(); - #ifndef _WIN32 /* force override (no zend_signals) to prevent crashes due to signal recursion in SIGSEGV/SIGBUS handlers */ signal(SIGSEGV, SIG_DFL); @@ -2173,6 +2171,8 @@ phpdbg_out: #endif } + php_module_shutdown(); + sapi_shutdown(); if (sapi_name) { -- cgit v1.2.1