Skip to content

Commit 68485f8

Browse files
committed
implement tsrm_is_shutdown API
1 parent bc0db8c commit 68485f8

File tree

5 files changed

+52
-90
lines changed

5 files changed

+52
-90
lines changed

TSRM/TSRM.c

Lines changed: 43 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,13 @@
1717
#include <stdio.h>
1818
#include <stdarg.h>
1919

20+
#ifdef ZEND_DEBUG
21+
# include <assert.h>
22+
# define TSRM_ASSERT assert
23+
#else
24+
# define TSRM_ASSERT
25+
#endif
26+
2027
typedef struct _tsrm_tls_entry tsrm_tls_entry;
2128

2229
/* TSRMLS_CACHE_DEFINE; is already done in Zend, this is being always compiled statically. */
@@ -123,6 +130,7 @@ static DWORD tls_key;
123130
#endif
124131

125132
TSRM_TLS uint8_t in_main_thread = 0;
133+
TSRM_TLS uint8_t is_thread_shutdown = 0;
126134

127135
/* Startup TSRM (call once for the entire process) */
128136
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
141149

142150
/* ensure singleton */
143151
in_main_thread = 1;
152+
is_thread_shutdown = 0;
144153

145154
tsrm_error_file = stderr;
146155
tsrm_error_set(debug_level, debug_filename);
@@ -149,6 +158,7 @@ TSRM_API int tsrm_startup(int expected_threads, int expected_resources, int debu
149158
tsrm_tls_table = (tsrm_tls_entry **) calloc(tsrm_tls_table_size, sizeof(tsrm_tls_entry *));
150159
if (!tsrm_tls_table) {
151160
TSRM_ERROR((TSRM_ERROR_LEVEL_ERROR, "Unable to allocate TLS table"));
161+
is_thread_shutdown = 1;
152162
return 0;
153163
}
154164
id_count=0;
@@ -157,8 +167,8 @@ TSRM_API int tsrm_startup(int expected_threads, int expected_resources, int debu
157167
resource_types_table = (tsrm_resource_type *) calloc(resource_types_table_size, sizeof(tsrm_resource_type));
158168
if (!resource_types_table) {
159169
TSRM_ERROR((TSRM_ERROR_LEVEL_ERROR, "Unable to allocate resource types table"));
170+
is_thread_shutdown = 1;
160171
free(tsrm_tls_table);
161-
tsrm_tls_table = NULL;
162172
return 0;
163173
}
164174

@@ -180,45 +190,44 @@ TSRM_API void tsrm_shutdown(void)
180190
{/*{{{*/
181191
int i;
182192

193+
if (is_thread_shutdown) {
194+
/* shutdown must only occur once */
195+
return;
196+
}
197+
198+
is_thread_shutdown = 1;
199+
183200
if (!in_main_thread) {
184-
/* ensure singleton */
201+
/* only the main thread may shutdown tsrm */
185202
return;
186203
}
187204

188-
if (tsrm_tls_table) {
189-
for (i=0; i<tsrm_tls_table_size; i++) {
190-
tsrm_tls_entry *p = tsrm_tls_table[i], *next_p;
205+
for (i=0; i<tsrm_tls_table_size; i++) {
206+
tsrm_tls_entry *p = tsrm_tls_table[i], *next_p;
191207

192-
while (p) {
193-
int j;
208+
while (p) {
209+
int j;
194210

195-
next_p = p->next;
196-
for (j=0; j<p->count; j++) {
197-
if (p->storage[j]) {
198-
if (resource_types_table && !resource_types_table[j].done && resource_types_table[j].dtor) {
199-
resource_types_table[j].dtor(p->storage[j]);
200-
}
201-
if (!resource_types_table[j].fast_offset) {
202-
free(p->storage[j]);
203-
}
211+
next_p = p->next;
212+
for (j=0; j<p->count; j++) {
213+
if (p->storage[j]) {
214+
if (resource_types_table && !resource_types_table[j].done && resource_types_table[j].dtor) {
215+
resource_types_table[j].dtor(p->storage[j]);
216+
}
217+
if (!resource_types_table[j].fast_offset) {
218+
free(p->storage[j]);
204219
}
205220
}
206-
free(p->storage);
207-
free(p);
208-
p = next_p;
209221
}
222+
free(p->storage);
223+
free(p);
224+
p = next_p;
210225
}
211-
free(tsrm_tls_table);
212-
tsrm_tls_table = NULL;
213-
}
214-
if (resource_types_table) {
215-
free(resource_types_table);
216-
resource_types_table=NULL;
217226
}
227+
free(tsrm_tls_table);
228+
free(resource_types_table);
218229
tsrm_mutex_free(tsmm_mutex);
219-
tsmm_mutex = NULL;
220230
tsrm_mutex_free(tsrm_env_mutex);
221-
tsrm_env_mutex = NULL;
222231
TSRM_ERROR((TSRM_ERROR_LEVEL_CORE, "Shutdown TSRM"));
223232
if (tsrm_error_file!=stderr) {
224233
fclose(tsrm_error_file);
@@ -556,6 +565,8 @@ void ts_free_thread(void)
556565
int hash_value;
557566
tsrm_tls_entry *last=NULL;
558567

568+
TSRM_ASSERT(!in_main_thread);
569+
559570
tsrm_mutex_lock(tsmm_mutex);
560571
hash_value = THREAD_HASH_OF(thread_id, tsrm_tls_table_size);
561572
thread_resources = tsrm_tls_table[hash_value];
@@ -590,55 +601,6 @@ void ts_free_thread(void)
590601
tsrm_mutex_unlock(tsmm_mutex);
591602
}/*}}}*/
592603

593-
594-
/* frees all resources allocated for all threads except current */
595-
void ts_free_worker_threads(void)
596-
{/*{{{*/
597-
tsrm_tls_entry *thread_resources;
598-
int i;
599-
THREAD_T thread_id = tsrm_thread_id();
600-
int hash_value;
601-
tsrm_tls_entry *last=NULL;
602-
603-
tsrm_mutex_lock(tsmm_mutex);
604-
hash_value = THREAD_HASH_OF(thread_id, tsrm_tls_table_size);
605-
thread_resources = tsrm_tls_table[hash_value];
606-
607-
while (thread_resources) {
608-
if (thread_resources->thread_id != thread_id) {
609-
for (i=0; i<thread_resources->count; i++) {
610-
if (resource_types_table[i].dtor) {
611-
resource_types_table[i].dtor(thread_resources->storage[i]);
612-
}
613-
}
614-
for (i=0; i<thread_resources->count; i++) {
615-
if (!resource_types_table[i].fast_offset) {
616-
free(thread_resources->storage[i]);
617-
}
618-
}
619-
free(thread_resources->storage);
620-
if (last) {
621-
last->next = thread_resources->next;
622-
} else {
623-
tsrm_tls_table[hash_value] = thread_resources->next;
624-
}
625-
free(thread_resources);
626-
if (last) {
627-
thread_resources = last->next;
628-
} else {
629-
thread_resources = tsrm_tls_table[hash_value];
630-
}
631-
} else {
632-
if (thread_resources->next) {
633-
last = thread_resources;
634-
}
635-
thread_resources = thread_resources->next;
636-
}
637-
}
638-
tsrm_mutex_unlock(tsmm_mutex);
639-
}/*}}}*/
640-
641-
642604
/* deallocates all occurrences of a given id */
643605
void ts_free_id(ts_rsrc_id id)
644606
{/*{{{*/
@@ -885,6 +847,11 @@ TSRM_API uint8_t tsrm_is_main_thread(void)
885847
return in_main_thread;
886848
}/*}}}*/
887849

850+
TSRM_API uint8_t tsrm_is_shutdown(void)
851+
{/*{{{*/
852+
return is_thread_shutdown;
853+
}/*}}}*/
854+
888855
TSRM_API const char *tsrm_api_name(void)
889856
{/*{{{*/
890857
#if defined(GNUPTH)

TSRM/TSRM.h

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -115,9 +115,6 @@ TSRM_API void *ts_resource_ex(ts_rsrc_id id, THREAD_T *th_id);
115115
/* frees all resources allocated for the current thread */
116116
TSRM_API void ts_free_thread(void);
117117

118-
/* frees all resources allocated for all threads except current */
119-
void ts_free_worker_threads(void);
120-
121118
/* deallocates all occurrences of a given id */
122119
TSRM_API void ts_free_id(ts_rsrc_id id);
123120

@@ -157,6 +154,7 @@ TSRM_API void tsrm_free_interpreter_context(void *context);
157154

158155
TSRM_API void *tsrm_get_ls_cache(void);
159156
TSRM_API uint8_t tsrm_is_main_thread(void);
157+
TSRM_API uint8_t tsrm_is_shutdown(void);
160158
TSRM_API const char *tsrm_api_name(void);
161159

162160
#ifdef TSRM_WIN32

Zend/zend_signal.c

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -82,16 +82,17 @@ void zend_signal_handler_defer(int signo, siginfo_t *siginfo, void *context)
8282
{
8383
int errno_save = errno;
8484
zend_signal_queue_t *queue, *qtmp;
85-
zend_bool is_handling_safe = 1;
8685

8786
#ifdef ZTS
8887
/* A signal could hit after TSRM shutdown, in this case globals are already freed. */
89-
if (NULL == TSRMLS_CACHE || NULL == TSRMG_BULK_STATIC(zend_signal_globals_id, zend_signal_globals_t *)) {
90-
is_handling_safe = 0;
88+
if (tsrm_is_shutdown()) {
89+
/* Forward to default handler handler */
90+
zend_signal_handler(signo, siginfo, context);
91+
return;
9192
}
9293
#endif
9394

94-
if (EXPECTED(is_handling_safe && SIGG(active))) {
95+
if (EXPECTED(SIGG(active))) {
9596
if (UNEXPECTED(SIGG(depth) == 0)) { /* try to handle signal */
9697
if (UNEXPECTED(SIGG(blocked))) {
9798
SIGG(blocked) = 0;
@@ -176,7 +177,7 @@ static void zend_signal_handler(int signo, siginfo_t *siginfo, void *context)
176177
sigset_t sigset;
177178
zend_signal_entry_t p_sig;
178179
#ifdef ZTS
179-
if (NULL == TSRMLS_CACHE || NULL == TSRMG_BULK_STATIC(zend_signal_globals_id, zend_signal_globals_t *)) {
180+
if (tsrm_is_shutdown()) {
180181
p_sig.flags = 0;
181182
p_sig.handler = SIG_DFL;
182183
} else

main/main.c

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2514,10 +2514,6 @@ void php_module_shutdown(void)
25142514

25152515
zend_interned_strings_switch_storage(0);
25162516

2517-
#ifdef ZTS
2518-
ts_free_worker_threads();
2519-
#endif
2520-
25212517
#if ZEND_RC_DEBUG
25222518
zend_rc_debug = 0;
25232519
#endif

sapi/phpdbg/phpdbg.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2161,8 +2161,6 @@ int main(int argc, char **argv) /* {{{ */
21612161
Z_PTR_P(zv) = (void*)PHPDBG_G(orig_url_wrap_php);
21622162
}
21632163

2164-
php_module_shutdown();
2165-
21662164
#ifndef _WIN32
21672165
/* force override (no zend_signals) to prevent crashes due to signal recursion in SIGSEGV/SIGBUS handlers */
21682166
signal(SIGSEGV, SIG_DFL);
@@ -2173,6 +2171,8 @@ int main(int argc, char **argv) /* {{{ */
21732171
#endif
21742172
}
21752173

2174+
php_module_shutdown();
2175+
21762176
sapi_shutdown();
21772177

21782178
if (sapi_name) {

0 commit comments

Comments
 (0)