diff options
Diffstat (limited to 'Zend/zend_execute_API.c')
-rw-r--r-- | Zend/zend_execute_API.c | 44 |
1 files changed, 29 insertions, 15 deletions
diff --git a/Zend/zend_execute_API.c b/Zend/zend_execute_API.c index f61a865ddc..ce51ef7960 100644 --- a/Zend/zend_execute_API.c +++ b/Zend/zend_execute_API.c @@ -278,6 +278,24 @@ void shutdown_executor(void) /* {{{ */ if (!fast_shutdown) { zend_hash_graceful_reverse_destroy(&EG(symbol_table)); + /* Constants may contain objects, destroy them before the object store. */ + if (EG(full_tables_cleanup)) { + zend_hash_reverse_apply(EG(zend_constants), clean_non_persistent_constant_full); + } else { + ZEND_HASH_REVERSE_FOREACH_STR_KEY_VAL(EG(zend_constants), key, zv) { + zend_constant *c = Z_PTR_P(zv); + if (_idx == EG(persistent_constants_count)) { + break; + } + zval_ptr_dtor_nogc(&c->value); + if (c->name) { + zend_string_release_ex(c->name, 0); + } + efree(c); + zend_string_release_ex(key, 0); + } ZEND_HASH_FOREACH_END_DEL(); + } + /* Release static properties and static variables prior to the final GC run, * as they may hold GC roots. */ ZEND_HASH_REVERSE_FOREACH_VAL(EG(function_table), zv) { @@ -302,6 +320,15 @@ void shutdown_executor(void) /* {{{ */ if (ZEND_MAP_PTR(ce->mutable_data) && ZEND_MAP_PTR_GET_IMM(ce->mutable_data)) { zend_cleanup_mutable_class_data(ce); + } else if (ce->type == ZEND_USER_CLASS && !(ce->ce_flags & ZEND_ACC_IMMUTABLE)) { + /* Constants may contain objects, destroy the values before the object store. */ + zend_class_constant *c; + ZEND_HASH_FOREACH_PTR(&ce->constants_table, c) { + if (c->ce == ce) { + zval_ptr_dtor_nogc(&c->value); + ZVAL_UNDEF(&c->value); + } + } ZEND_HASH_FOREACH_END(); } if (ce->ce_flags & ZEND_HAS_STATIC_IN_METHODS) { @@ -340,6 +367,8 @@ void shutdown_executor(void) /* {{{ */ gc_collect_cycles(); } #endif + } else { + zend_hash_discard(EG(zend_constants), EG(persistent_constants_count)); } zend_objects_store_free_object_storage(&EG(objects_store), fast_shutdown); @@ -356,7 +385,6 @@ void shutdown_executor(void) /* {{{ */ * Zend Memory Manager frees memory by its own. We don't have to free * each allocated block separately. */ - zend_hash_discard(EG(zend_constants), EG(persistent_constants_count)); zend_hash_discard(EG(function_table), EG(persistent_functions_count)); zend_hash_discard(EG(class_table), EG(persistent_classes_count)); zend_cleanup_internal_classes(); @@ -364,23 +392,9 @@ void shutdown_executor(void) /* {{{ */ zend_vm_stack_destroy(); if (EG(full_tables_cleanup)) { - zend_hash_reverse_apply(EG(zend_constants), clean_non_persistent_constant_full); zend_hash_reverse_apply(EG(function_table), clean_non_persistent_function_full); zend_hash_reverse_apply(EG(class_table), clean_non_persistent_class_full); } else { - ZEND_HASH_REVERSE_FOREACH_STR_KEY_VAL(EG(zend_constants), key, zv) { - zend_constant *c = Z_PTR_P(zv); - if (_idx == EG(persistent_constants_count)) { - break; - } - zval_ptr_dtor_nogc(&c->value); - if (c->name) { - zend_string_release_ex(c->name, 0); - } - efree(c); - zend_string_release_ex(key, 0); - } ZEND_HASH_FOREACH_END_DEL(); - ZEND_HASH_REVERSE_FOREACH_STR_KEY_VAL(EG(function_table), key, zv) { zend_function *func = Z_PTR_P(zv); if (_idx == EG(persistent_functions_count)) { |