diff --git a/TSRM/TSRM.c b/TSRM/TSRM.c index 09ff8cc49279e..5d1ae304098da 100644 --- a/TSRM/TSRM.c +++ b/TSRM/TSRM.c @@ -576,6 +576,27 @@ void ts_free_id(ts_rsrc_id id) TSRM_ERROR((TSRM_ERROR_LEVEL_CORE, "Successfully freed resource id %d", id)); }/*}}}*/ +TSRM_API void ts_apply_for_id(ts_rsrc_id id, void (*cb)(void *)) +{ + int rsrc_id = TSRM_UNSHUFFLE_RSRC_ID(id); + + tsrm_mutex_lock(tsmm_mutex); + + if (tsrm_tls_table && resource_types_table) { + for (int i = 0; i < tsrm_tls_table_size; i++) { + tsrm_tls_entry *p = tsrm_tls_table[i]; + + while (p) { + if (p->count > rsrc_id && p->storage[rsrc_id]) { + cb(p->storage[rsrc_id]); + } + p = p->next; + } + } + } + + tsrm_mutex_unlock(tsmm_mutex); +} /* * Utility Functions diff --git a/TSRM/TSRM.h b/TSRM/TSRM.h index 3bb32e4da289a..c9e8edd37224b 100644 --- a/TSRM/TSRM.h +++ b/TSRM/TSRM.h @@ -104,6 +104,9 @@ TSRM_API void ts_free_thread(void); /* deallocates all occurrences of a given id */ TSRM_API void ts_free_id(ts_rsrc_id id); +/* Runs a callback on all resources of the given id. + * The caller is responsible for ensuring the underlying resources don't data-race. */ +TSRM_API void ts_apply_for_id(ts_rsrc_id id, void (*cb)(void *)); /* Debug support */ #define TSRM_ERROR_LEVEL_ERROR 1 diff --git a/Zend/zend.c b/Zend/zend.c index 12efe56a63b05..6e7f4890f7eec 100644 --- a/Zend/zend.c +++ b/Zend/zend.c @@ -826,13 +826,19 @@ static void executor_globals_ctor(zend_executor_globals *executor_globals) /* {{ } /* }}} */ -static void executor_globals_dtor(zend_executor_globals *executor_globals) /* {{{ */ +static void executor_globals_persistent_list_dtor(void *storage) { - zend_ini_dtor(executor_globals->ini_directives); + zend_executor_globals *executor_globals = storage; if (&executor_globals->persistent_list != global_persistent_list) { zend_destroy_rsrc_list(&executor_globals->persistent_list); } +} + +static void executor_globals_dtor(zend_executor_globals *executor_globals) /* {{{ */ +{ + zend_ini_dtor(executor_globals->ini_directives); + if (executor_globals->zend_constants != GLOBAL_CONSTANTS_TABLE) { zend_hash_destroy(executor_globals->zend_constants); free(executor_globals->zend_constants); @@ -1122,6 +1128,9 @@ void zend_shutdown(void) /* {{{ */ zend_vm_dtor(); zend_destroy_rsrc_list(&EG(persistent_list)); +#ifdef ZTS + ts_apply_for_id(executor_globals_id, executor_globals_persistent_list_dtor); +#endif zend_destroy_modules(); virtual_cwd_deactivate(); diff --git a/ext/odbc/php_odbc.c b/ext/odbc/php_odbc.c index cd3877edc6bfe..1866a8f14d12d 100644 --- a/ext/odbc/php_odbc.c +++ b/ext/odbc/php_odbc.c @@ -168,13 +168,7 @@ static void _close_odbc_conn(zend_resource *rsrc) SQLFreeEnv(conn->henv); } efree(conn); - /* See https://github.com/php/php-src/issues/12974 why we need to check the if */ -#ifdef ZTS - if (odbc_module_entry.module_started) -#endif - { - ODBCG(num_links)--; - } + ODBCG(num_links)--; } /* }}} */ diff --git a/ext/pgsql/pgsql.c b/ext/pgsql/pgsql.c index 2356d8857c8dd..860d007cfc01d 100644 --- a/ext/pgsql/pgsql.c +++ b/ext/pgsql/pgsql.c @@ -315,14 +315,8 @@ static void _close_pgsql_plink(zend_resource *rsrc) PQclear(res); } PQfinish(link); - /* See https://github.com/php/php-src/issues/12974 why we need to check the if */ -#ifdef ZTS - if (pgsql_module_entry.module_started) -#endif - { - PGG(num_persistent)--; - PGG(num_links)--; - } + PGG(num_persistent)--; + PGG(num_links)--; rsrc->ptr = NULL; }