summaryrefslogtreecommitdiff
path: root/Zend/zend_execute_API.c
diff options
context:
space:
mode:
authorNikita Popov <nikita.ppv@gmail.com>2019-08-28 12:15:28 +0200
committerNikita Popov <nikita.ppv@gmail.com>2019-08-28 12:32:06 +0200
commitec9a96dc60c3fd2cccf5b21033a0e87807366bdb (patch)
treec2297d26040f658eb4d1df423a6f21a147423c49 /Zend/zend_execute_API.c
parent8dfd3af169f05c45f46b7ddb9599f22e086e4884 (diff)
downloadphp-git-ec9a96dc60c3fd2cccf5b21033a0e87807366bdb.tar.gz
Fixed bug #78335
Destroy static properties and variables prior to the final GC run, as they may hold GC roots.
Diffstat (limited to 'Zend/zend_execute_API.c')
-rw-r--r--Zend/zend_execute_API.c93
1 files changed, 45 insertions, 48 deletions
diff --git a/Zend/zend_execute_API.c b/Zend/zend_execute_API.c
index 161390e22a..ac2ee8ed7f 100644
--- a/Zend/zend_execute_API.c
+++ b/Zend/zend_execute_API.c
@@ -270,9 +270,54 @@ void shutdown_executor(void) /* {{{ */
zend_close_rsrc_list(&EG(regular_list));
} zend_end_try();
+ /* No PHP callback functions should be called after this point. */
+ EG(active) = 0;
+
if (!fast_shutdown) {
zend_hash_graceful_reverse_destroy(&EG(symbol_table));
+ /* 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) {
+ zend_op_array *op_array = Z_PTR_P(zv);
+ if (op_array->type == ZEND_INTERNAL_FUNCTION) {
+ break;
+ }
+ if (op_array->static_variables) {
+ HashTable *ht = ZEND_MAP_PTR_GET(op_array->static_variables_ptr);
+ if (ht) {
+ ZEND_ASSERT(GC_REFCOUNT(ht) == 1);
+ zend_array_destroy(ht);
+ ZEND_MAP_PTR_SET(op_array->static_variables_ptr, NULL);
+ }
+ }
+ } ZEND_HASH_FOREACH_END();
+ ZEND_HASH_REVERSE_FOREACH_VAL(EG(class_table), zv) {
+ zend_class_entry *ce = Z_PTR_P(zv);
+ if (ce->type == ZEND_INTERNAL_CLASS) {
+ break;
+ }
+ if (ce->default_static_members_count) {
+ zend_cleanup_internal_class_data(ce);
+ }
+ if (ce->ce_flags & ZEND_HAS_STATIC_IN_METHODS) {
+ zend_op_array *op_array;
+ ZEND_HASH_FOREACH_PTR(&ce->function_table, op_array) {
+ if (op_array->type == ZEND_USER_FUNCTION) {
+ if (op_array->static_variables) {
+ HashTable *ht = ZEND_MAP_PTR_GET(op_array->static_variables_ptr);
+ if (ht) {
+ if (GC_DELREF(ht) == 0) {
+ zend_array_destroy(ht);
+ }
+ ZEND_MAP_PTR_SET(op_array->static_variables_ptr, NULL);
+ }
+ }
+ }
+ } ZEND_HASH_FOREACH_END();
+ }
+ } ZEND_HASH_FOREACH_END();
+
#if ZEND_DEBUG
if (gc_enabled() && !CG(unclean_shutdown)) {
gc_collect_cycles();
@@ -284,10 +329,6 @@ void shutdown_executor(void) /* {{{ */
zend_weakrefs_shutdown();
- /* All resources and objects are destroyed. */
- /* No PHP callback functions may be called after this point. */
- EG(active) = 0;
-
zend_try {
zend_llist_apply(&zend_extensions, (llist_apply_func_t) zend_extension_deactivator);
} zend_end_try();
@@ -348,23 +389,6 @@ void shutdown_executor(void) /* {{{ */
zend_string_release_ex(key, 0);
} ZEND_HASH_FOREACH_END_DEL();
- /* Cleanup preloaded immutable functions */
- ZEND_HASH_REVERSE_FOREACH_VAL(EG(function_table), zv) {
- zend_op_array *op_array = Z_PTR_P(zv);
- if (op_array->type == ZEND_INTERNAL_FUNCTION) {
- break;
- }
- ZEND_ASSERT(op_array->fn_flags & ZEND_ACC_IMMUTABLE);
- if (op_array->static_variables) {
- HashTable *ht = ZEND_MAP_PTR_GET(op_array->static_variables_ptr);
- if (ht) {
- ZEND_ASSERT(GC_REFCOUNT(ht) == 1);
- zend_array_destroy(ht);
- ZEND_MAP_PTR_SET(op_array->static_variables_ptr, NULL);
- }
- }
- } ZEND_HASH_FOREACH_END();
-
ZEND_HASH_REVERSE_FOREACH_STR_KEY_VAL(EG(class_table), key, zv) {
if (_idx == EG(persistent_classes_count)) {
break;
@@ -372,33 +396,6 @@ void shutdown_executor(void) /* {{{ */
destroy_zend_class(zv);
zend_string_release_ex(key, 0);
} ZEND_HASH_FOREACH_END_DEL();
-
- /* Cleanup preloaded immutable classes */
- ZEND_HASH_REVERSE_FOREACH_VAL(EG(class_table), zv) {
- zend_class_entry *ce = Z_PTR_P(zv);
- if (ce->type == ZEND_INTERNAL_CLASS) {
- break;
- }
- ZEND_ASSERT(ce->ce_flags & ZEND_ACC_IMMUTABLE);
- if (ce->default_static_members_count) {
- zend_cleanup_internal_class_data(ce);
- }
- if (ce->ce_flags & ZEND_HAS_STATIC_IN_METHODS) {
- zend_op_array *op_array;
- ZEND_HASH_FOREACH_PTR(&ce->function_table, op_array) {
- if (op_array->type == ZEND_USER_FUNCTION) {
- if (op_array->static_variables) {
- HashTable *ht = ZEND_MAP_PTR_GET(op_array->static_variables_ptr);
- if (ht) {
- ZEND_ASSERT(GC_REFCOUNT(ht) == 1);
- zend_array_destroy(ht);
- ZEND_MAP_PTR_SET(op_array->static_variables_ptr, NULL);
- }
- }
- }
- } ZEND_HASH_FOREACH_END();
- }
- } ZEND_HASH_FOREACH_END();
}
zend_cleanup_internal_classes();