summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Zend/zend_execute_API.c44
-rw-r--r--Zend/zend_objects_API.c5
2 files changed, 30 insertions, 19 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)) {
diff --git a/Zend/zend_objects_API.c b/Zend/zend_objects_API.c
index b0e9d2f8a8..104cda6141 100644
--- a/Zend/zend_objects_API.c
+++ b/Zend/zend_objects_API.c
@@ -113,10 +113,7 @@ ZEND_API void ZEND_FASTCALL zend_objects_store_free_object_storage(zend_objects_
if (IS_OBJ_VALID(obj)) {
if (!(OBJ_FLAGS(obj) & IS_OBJ_FREE_CALLED)) {
GC_ADD_FLAGS(obj, IS_OBJ_FREE_CALLED);
- // FIXME: This causes constant objects to leak
- if (!(obj->ce->ce_flags & ZEND_ACC_ENUM)) {
- GC_ADDREF(obj);
- }
+ GC_ADDREF(obj);
obj->handlers->free_obj(obj);
}
}