Destroy static properties and variables prior to the final GC run,
as they may hold GC roots.
This commit is contained in:
Nikita Popov 2019-08-28 12:15:28 +02:00
parent 8dfd3af169
commit ec9a96dc60
3 changed files with 75 additions and 48 deletions

View file

@ -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();