@@ -100,28 +100,21 @@ static void zend_extension_deactivator(zend_extension *extension) /* {{{ */
100
100
}
101
101
/* }}} */
102
102
103
- static int clean_non_persistent_function (zval * zv ) /* {{{ */
103
+ static int clean_non_persistent_constant_full (zval * zv ) /* {{{ */
104
104
{
105
- zend_function * function = Z_PTR_P (zv );
106
- return (function -> type == ZEND_INTERNAL_FUNCTION ) ? ZEND_HASH_APPLY_STOP : ZEND_HASH_APPLY_REMOVE ;
105
+ zend_constant * c = Z_PTR_P (zv );
106
+ return (c -> flags & CONST_PERSISTENT ) ? ZEND_HASH_APPLY_KEEP : ZEND_HASH_APPLY_REMOVE ;
107
107
}
108
108
/* }}} */
109
109
110
- ZEND_API int clean_non_persistent_function_full (zval * zv ) /* {{{ */
110
+ static int clean_non_persistent_function_full (zval * zv ) /* {{{ */
111
111
{
112
112
zend_function * function = Z_PTR_P (zv );
113
113
return (function -> type == ZEND_INTERNAL_FUNCTION ) ? ZEND_HASH_APPLY_KEEP : ZEND_HASH_APPLY_REMOVE ;
114
114
}
115
115
/* }}} */
116
116
117
- static int clean_non_persistent_class (zval * zv ) /* {{{ */
118
- {
119
- zend_class_entry * ce = Z_PTR_P (zv );
120
- return (ce -> type == ZEND_INTERNAL_CLASS ) ? ZEND_HASH_APPLY_STOP : ZEND_HASH_APPLY_REMOVE ;
121
- }
122
- /* }}} */
123
-
124
- ZEND_API int clean_non_persistent_class_full (zval * zv ) /* {{{ */
117
+ static int clean_non_persistent_class_full (zval * zv ) /* {{{ */
125
118
{
126
119
zend_class_entry * ce = Z_PTR_P (zv );
127
120
return (ce -> type == ZEND_INTERNAL_CLASS ) ? ZEND_HASH_APPLY_KEEP : ZEND_HASH_APPLY_REMOVE ;
@@ -253,136 +246,124 @@ void shutdown_destructors(void) /* {{{ */
253
246
254
247
void shutdown_executor (void ) /* {{{ */
255
248
{
256
- zend_function * func ;
257
- zend_class_entry * ce ;
249
+ zend_string * key ;
250
+ zval * zv ;
251
+ #if ZEND_DEBUG
252
+ zend_bool fast_shutdown = 0 ;
253
+ #else
254
+ zend_bool fast_shutdown = is_zend_mm () && !EG (full_tables_cleanup );
255
+ #endif
258
256
259
257
zend_try {
258
+ zend_llist_destroy (& CG (open_files ));
259
+ } zend_end_try ();
260
260
261
- /* Removed because this can not be safely done, e.g. in this situation:
262
- Object 1 creates object 2
263
- Object 3 holds reference to object 2.
264
- Now when 1 and 2 are destroyed, 3 can still access 2 in its destructor, with
265
- very problematic results */
266
- /* zend_objects_store_call_destructors(&EG(objects_store)); */
261
+ zend_try {
262
+ zend_close_rsrc_list (& EG (regular_list ));
263
+ } zend_end_try ();
267
264
268
- /* Moved after symbol table cleaners, because some of the cleaners can call
269
- destructors, which would use EG(symtable_cache_ptr) and thus leave leaks */
270
- /* while (EG(symtable_cache_ptr)>=EG(symtable_cache)) {
271
- zend_hash_destroy(*EG(symtable_cache_ptr));
272
- efree(*EG(symtable_cache_ptr));
273
- EG(symtable_cache_ptr)--;
274
- }
275
- */
276
- zend_llist_apply (& zend_extensions , (llist_apply_func_t ) zend_extension_deactivator );
265
+ zend_objects_store_free_object_storage (& EG (objects_store ), fast_shutdown );
277
266
278
- zend_hash_graceful_reverse_destroy (& EG (symbol_table ));
267
+ /* All resources and objects are destroyed. */
268
+ /* No PHP callback functions may be called after this point. */
269
+
270
+ zend_try {
271
+ zend_llist_apply (& zend_extensions , (llist_apply_func_t ) zend_extension_deactivator );
279
272
} zend_end_try ();
273
+
280
274
EG (valid_symbol_table ) = 0 ;
281
275
282
- zend_try {
283
- zval * zeh ;
276
+ if (fast_shutdown ) {
277
+ /* Fast Request Shutdown
278
+ * =====================
279
+ * Zend Memory Manager frees memory by its own. We don't have to free
280
+ * each allocated block separately.
281
+ */
282
+ ZEND_HASH_REVERSE_FOREACH_VAL (EG (zend_constants ), zv ) {
283
+ zend_constant * c = Z_PTR_P (zv );
284
+ if (c -> flags & CONST_PERSISTENT ) {
285
+ break ;
286
+ }
287
+ } ZEND_HASH_FOREACH_END_DEL ();
288
+ ZEND_HASH_REVERSE_FOREACH_VAL (EG (function_table ), zv ) {
289
+ zend_function * func = Z_PTR_P (zv );
290
+ if (func -> type == ZEND_INTERNAL_FUNCTION ) {
291
+ break ;
292
+ }
293
+ } ZEND_HASH_FOREACH_END_DEL ();
294
+ ZEND_HASH_REVERSE_FOREACH_VAL (EG (class_table ), zv ) {
295
+ zend_class_entry * ce = Z_PTR_P (zv );
296
+ if (ce -> type == ZEND_INTERNAL_CLASS ) {
297
+ break ;
298
+ }
299
+ } ZEND_HASH_FOREACH_END_DEL ();
300
+ } else {
301
+ zend_hash_graceful_reverse_destroy (& EG (symbol_table ));
302
+
303
+ #if ZEND_DEBUG
304
+ if (GC_G (gc_enabled ) && !CG (unclean_shutdown )) {
305
+ gc_collect_cycles ();
306
+ }
307
+ #endif
308
+
284
309
/* remove error handlers before destroying classes and functions,
285
310
* so that if handler used some class, crash would not happen */
286
311
if (Z_TYPE (EG (user_error_handler )) != IS_UNDEF ) {
287
- zeh = & EG (user_error_handler );
288
- zval_ptr_dtor (zeh );
312
+ zval_ptr_dtor (& EG (user_error_handler ));
289
313
ZVAL_UNDEF (& EG (user_error_handler ));
290
314
}
291
315
292
316
if (Z_TYPE (EG (user_exception_handler )) != IS_UNDEF ) {
293
- zeh = & EG (user_exception_handler );
294
- zval_ptr_dtor (zeh );
317
+ zval_ptr_dtor (& EG (user_exception_handler ));
295
318
ZVAL_UNDEF (& EG (user_exception_handler ));
296
319
}
297
320
298
321
zend_stack_clean (& EG (user_error_handlers_error_reporting ), NULL , 1 );
299
322
zend_stack_clean (& EG (user_error_handlers ), (void (* )(void * ))ZVAL_PTR_DTOR , 1 );
300
323
zend_stack_clean (& EG (user_exception_handlers ), (void (* )(void * ))ZVAL_PTR_DTOR , 1 );
301
- } zend_end_try ();
302
324
303
- zend_try {
304
- /* Cleanup static data for functions and arrays.
305
- * We need a separate cleanup stage because of the following problem:
306
- * Suppose we destroy class X, which destroys the class's function table,
307
- * and in the function table we have function foo() that has static $bar.
308
- * Now if an object of class X is assigned to $bar, its destructor will be
309
- * called and will fail since X's function table is in mid-destruction.
310
- * So we want first of all to clean up all data and then move to tables destruction.
311
- * Note that only run-time accessed data need to be cleaned up, pre-defined data can
312
- * not contain objects and thus are not probelmatic */
325
+ zend_vm_stack_destroy ();
326
+
313
327
if (EG (full_tables_cleanup )) {
314
- ZEND_HASH_FOREACH_PTR (EG (function_table ), func ) {
315
- if (func -> type == ZEND_USER_FUNCTION ) {
316
- zend_cleanup_op_array_data ((zend_op_array * ) func );
328
+ zend_hash_reverse_apply (EG (zend_constants ), clean_non_persistent_constant_full );
329
+ zend_hash_reverse_apply (EG (function_table ), clean_non_persistent_function_full );
330
+ zend_hash_reverse_apply (EG (class_table ), clean_non_persistent_class_full );
331
+ } else {
332
+ ZEND_HASH_REVERSE_FOREACH_STR_KEY_VAL (EG (zend_constants ), key , zv ) {
333
+ zend_constant * c = Z_PTR_P (zv );
334
+ if (c -> flags & CONST_PERSISTENT ) {
335
+ break ;
317
336
}
318
- } ZEND_HASH_FOREACH_END ();
319
- ZEND_HASH_REVERSE_FOREACH_PTR (EG (class_table ), ce ) {
320
- if (ce -> type == ZEND_USER_CLASS ) {
321
- zend_cleanup_user_class_data (ce );
322
- } else {
323
- zend_cleanup_internal_class_data (ce );
337
+ zval_ptr_dtor (& c -> value );
338
+ if (c -> name ) {
339
+ zend_string_release (c -> name );
324
340
}
325
- } ZEND_HASH_FOREACH_END ();
326
- } else {
327
- ZEND_HASH_REVERSE_FOREACH_PTR (EG (function_table ), func ) {
328
- if (func -> type != ZEND_USER_FUNCTION ) {
341
+ efree (c );
342
+ zend_string_release (key );
343
+ } ZEND_HASH_FOREACH_END_DEL ();
344
+ ZEND_HASH_REVERSE_FOREACH_STR_KEY_VAL (EG (function_table ), key , zv ) {
345
+ zend_function * func = Z_PTR_P (zv );
346
+ if (func -> type == ZEND_INTERNAL_FUNCTION ) {
329
347
break ;
330
348
}
331
- zend_cleanup_op_array_data ((zend_op_array * ) func );
332
- } ZEND_HASH_FOREACH_END ();
333
- ZEND_HASH_REVERSE_FOREACH_PTR (EG (class_table ), ce ) {
334
- if (ce -> type != ZEND_USER_CLASS ) {
349
+ destroy_op_array (& func -> op_array );
350
+ zend_string_release (key );
351
+ } ZEND_HASH_FOREACH_END_DEL ();
352
+ ZEND_HASH_REVERSE_FOREACH_STR_KEY_VAL (EG (class_table ), key , zv ) {
353
+ zend_class_entry * ce = Z_PTR_P (zv );
354
+ if (ce -> type == ZEND_INTERNAL_CLASS ) {
335
355
break ;
336
356
}
337
- zend_cleanup_user_class_data (ce );
338
- } ZEND_HASH_FOREACH_END ();
339
- zend_cleanup_internal_classes ();
340
- }
341
- } zend_end_try ();
342
-
343
- zend_try {
344
- zend_llist_destroy (& CG (open_files ));
345
- } zend_end_try ();
346
-
347
- zend_try {
348
- clean_non_persistent_constants ();
349
- } zend_end_try ();
350
-
351
- zend_try {
352
- zend_close_rsrc_list (& EG (regular_list ));
353
- } zend_end_try ();
354
-
355
- #if ZEND_DEBUG
356
- if (GC_G (gc_enabled ) && !CG (unclean_shutdown )) {
357
- gc_collect_cycles ();
358
- }
359
- #endif
360
-
361
- zend_try {
362
- zend_objects_store_free_object_storage (& EG (objects_store ));
363
-
364
- zend_vm_stack_destroy ();
365
-
366
- /* Destroy all op arrays */
367
- if (EG (full_tables_cleanup )) {
368
- zend_hash_reverse_apply (EG (function_table ), clean_non_persistent_function_full );
369
- zend_hash_reverse_apply (EG (class_table ), clean_non_persistent_class_full );
370
- } else {
371
- zend_hash_reverse_apply (EG (function_table ), clean_non_persistent_function );
372
- zend_hash_reverse_apply (EG (class_table ), clean_non_persistent_class );
357
+ destroy_zend_class (zv );
358
+ zend_string_release (key );
359
+ } ZEND_HASH_FOREACH_END_DEL ();
373
360
}
374
361
375
362
while (EG (symtable_cache_ptr )>=EG (symtable_cache )) {
376
363
zend_hash_destroy (* EG (symtable_cache_ptr ));
377
364
FREE_HASHTABLE (* EG (symtable_cache_ptr ));
378
365
EG (symtable_cache_ptr )-- ;
379
366
}
380
- } zend_end_try ();
381
-
382
- zend_try {
383
- #if 0 && ZEND_DEBUG
384
- signal (SIGSEGV , original_sigsegv_handler );
385
- #endif
386
367
387
368
zend_hash_destroy (& EG (included_files ));
388
369
@@ -394,9 +375,11 @@ void shutdown_executor(void) /* {{{ */
394
375
zend_hash_destroy (EG (in_autoload ));
395
376
FREE_HASHTABLE (EG (in_autoload ));
396
377
}
397
- } zend_end_try ();
398
378
399
- zend_shutdown_fpu ();
379
+ if (EG (ht_iterators ) != EG (ht_iterators_slots )) {
380
+ efree (EG (ht_iterators ));
381
+ }
382
+ }
400
383
401
384
#if ZEND_DEBUG
402
385
if (EG (ht_iterators_used ) && !CG (unclean_shutdown )) {
@@ -405,9 +388,10 @@ void shutdown_executor(void) /* {{{ */
405
388
#endif
406
389
407
390
EG (ht_iterators_used ) = 0 ;
408
- if (EG (ht_iterators ) != EG (ht_iterators_slots )) {
409
- efree (EG (ht_iterators ));
410
- }
391
+
392
+ zend_cleanup_internal_classes ();
393
+
394
+ zend_shutdown_fpu ();
411
395
412
396
EG (active ) = 0 ;
413
397
}
0 commit comments