17
17
#include <stdio.h>
18
18
#include <stdarg.h>
19
19
20
+ #ifdef ZEND_DEBUG
21
+ # include <assert.h>
22
+ # define TSRM_ASSERT assert
23
+ #else
24
+ # define TSRM_ASSERT
25
+ #endif
26
+
20
27
typedef struct _tsrm_tls_entry tsrm_tls_entry ;
21
28
22
29
/* TSRMLS_CACHE_DEFINE; is already done in Zend, this is being always compiled statically. */
@@ -123,6 +130,7 @@ static DWORD tls_key;
123
130
#endif
124
131
125
132
TSRM_TLS uint8_t in_main_thread = 0 ;
133
+ TSRM_TLS uint8_t is_thread_shutdown = 0 ;
126
134
127
135
/* Startup TSRM (call once for the entire process) */
128
136
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
141
149
142
150
/* ensure singleton */
143
151
in_main_thread = 1 ;
152
+ is_thread_shutdown = 0 ;
144
153
145
154
tsrm_error_file = stderr ;
146
155
tsrm_error_set (debug_level , debug_filename );
@@ -149,6 +158,7 @@ TSRM_API int tsrm_startup(int expected_threads, int expected_resources, int debu
149
158
tsrm_tls_table = (tsrm_tls_entry * * ) calloc (tsrm_tls_table_size , sizeof (tsrm_tls_entry * ));
150
159
if (!tsrm_tls_table ) {
151
160
TSRM_ERROR ((TSRM_ERROR_LEVEL_ERROR , "Unable to allocate TLS table" ));
161
+ is_thread_shutdown = 1 ;
152
162
return 0 ;
153
163
}
154
164
id_count = 0 ;
@@ -157,8 +167,8 @@ TSRM_API int tsrm_startup(int expected_threads, int expected_resources, int debu
157
167
resource_types_table = (tsrm_resource_type * ) calloc (resource_types_table_size , sizeof (tsrm_resource_type ));
158
168
if (!resource_types_table ) {
159
169
TSRM_ERROR ((TSRM_ERROR_LEVEL_ERROR , "Unable to allocate resource types table" ));
170
+ is_thread_shutdown = 1 ;
160
171
free (tsrm_tls_table );
161
- tsrm_tls_table = NULL ;
162
172
return 0 ;
163
173
}
164
174
@@ -180,45 +190,44 @@ TSRM_API void tsrm_shutdown(void)
180
190
{/*{{{*/
181
191
int i ;
182
192
193
+ if (is_thread_shutdown ) {
194
+ /* shutdown must only occur once */
195
+ return ;
196
+ }
197
+
198
+ is_thread_shutdown = 1 ;
199
+
183
200
if (!in_main_thread ) {
184
- /* ensure singleton */
201
+ /* only the main thread may shutdown tsrm */
185
202
return ;
186
203
}
187
204
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 ;
191
207
192
- while (p ) {
193
- int j ;
208
+ while (p ) {
209
+ int j ;
194
210
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 ]);
204
219
}
205
220
}
206
- free (p -> storage );
207
- free (p );
208
- p = next_p ;
209
221
}
222
+ free (p -> storage );
223
+ free (p );
224
+ p = next_p ;
210
225
}
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 ;
217
226
}
227
+ free (tsrm_tls_table );
228
+ free (resource_types_table );
218
229
tsrm_mutex_free (tsmm_mutex );
219
- tsmm_mutex = NULL ;
220
230
tsrm_mutex_free (tsrm_env_mutex );
221
- tsrm_env_mutex = NULL ;
222
231
TSRM_ERROR ((TSRM_ERROR_LEVEL_CORE , "Shutdown TSRM" ));
223
232
if (tsrm_error_file != stderr ) {
224
233
fclose (tsrm_error_file );
@@ -556,6 +565,8 @@ void ts_free_thread(void)
556
565
int hash_value ;
557
566
tsrm_tls_entry * last = NULL ;
558
567
568
+ TSRM_ASSERT (!in_main_thread );
569
+
559
570
tsrm_mutex_lock (tsmm_mutex );
560
571
hash_value = THREAD_HASH_OF (thread_id , tsrm_tls_table_size );
561
572
thread_resources = tsrm_tls_table [hash_value ];
@@ -590,55 +601,6 @@ void ts_free_thread(void)
590
601
tsrm_mutex_unlock (tsmm_mutex );
591
602
}/*}}}*/
592
603
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
-
642
604
/* deallocates all occurrences of a given id */
643
605
void ts_free_id (ts_rsrc_id id )
644
606
{/*{{{*/
@@ -885,6 +847,11 @@ TSRM_API uint8_t tsrm_is_main_thread(void)
885
847
return in_main_thread ;
886
848
}/*}}}*/
887
849
850
+ TSRM_API uint8_t tsrm_is_shutdown (void )
851
+ {/*{{{*/
852
+ return is_thread_shutdown ;
853
+ }/*}}}*/
854
+
888
855
TSRM_API const char * tsrm_api_name (void )
889
856
{/*{{{*/
890
857
#if defined(GNUPTH )
0 commit comments