From: Andi Gutmans Date: Fri, 25 Jan 2002 12:55:03 +0000 (+0000) Subject: - First destructor hell fix. There was a situation where an object's X-Git-Tag: PRE_ISSET_PATCH~81 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=7309a6ed21b85771e478d0513dc13dfadceeae16;p=php - First destructor hell fix. There was a situation where an object's - destructor could be run after its class was already dead. Right now - object destructors is the first thing whic happens during shutdown in - order to prevent this problem. It's very likely that destructors will - cause more grief and we'll have to outline exactly when you should use - them and what kind of logic you're allowed to do inside of them. - This bug was reported by sebastian. --- diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c index 2a02ac60f6..0132bb9ab0 100644 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@ -1365,7 +1365,7 @@ static void create_class(HashTable *class_table, char *name, int name_length, ze zend_hash_init(&new_class_entry.function_table, 10, NULL, ZEND_FUNCTION_DTOR, 0); zend_hash_init(&new_class_entry.class_table, 10, NULL, ZEND_CLASS_DTOR, 0); zend_hash_init(&new_class_entry.default_properties, 10, NULL, ZVAL_PTR_DTOR, 0); - new_class_entry.static_members = (HashTable *) emalloc(sizeof(HashTable)); + ALLOC_HASHTABLE(new_class_entry.static_members); zend_hash_init(new_class_entry.static_members, 10, NULL, ZVAL_PTR_DTOR, 0); zend_hash_init(&new_class_entry.constants_table, 10, NULL, ZVAL_PTR_DTOR, 0); @@ -1854,7 +1854,7 @@ void zend_do_begin_class_declaration(znode *class_token, znode *class_name, znod zend_hash_init(&new_class_entry.function_table, 10, NULL, ZEND_FUNCTION_DTOR, 0); zend_hash_init(&new_class_entry.class_table, 10, NULL, ZEND_CLASS_DTOR, 0); zend_hash_init(&new_class_entry.default_properties, 10, NULL, ZVAL_PTR_DTOR, 0); - new_class_entry.static_members = (HashTable *) emalloc(sizeof(HashTable)); + ALLOC_HASHTABLE(new_class_entry.static_members); zend_hash_init(new_class_entry.static_members, 10, NULL, ZVAL_PTR_DTOR, 0); zend_hash_init(&new_class_entry.constants_table, 10, NULL, ZVAL_PTR_DTOR, 0); diff --git a/Zend/zend_execute_API.c b/Zend/zend_execute_API.c index 12d28b1789..e116a5ca03 100644 --- a/Zend/zend_execute_API.c +++ b/Zend/zend_execute_API.c @@ -181,6 +181,8 @@ void init_executor(TSRMLS_D) void shutdown_executor(TSRMLS_D) { zend_try { + zend_objects_call_destructors(&EG(objects) TSRMLS_CC); + zend_ptr_stack_destroy(&EG(arg_types_stack)); while (EG(symtable_cache_ptr)>=EG(symtable_cache)) { diff --git a/Zend/zend_objects.c b/Zend/zend_objects.c index 4ff6bab921..bdb77f05d0 100644 --- a/Zend/zend_objects.c +++ b/Zend/zend_objects.c @@ -27,7 +27,7 @@ void zend_objects_destroy(zend_objects *objects) efree(objects->object_buckets); } -static inline void zend_objects_destroy_object(zend_object *object, zend_object_handle handle TSRMLS_DC) +static inline void zend_objects_call_destructor(zend_object *object, zend_object_handle handle TSRMLS_DC) { if (object->ce->destructor) { zval *obj; @@ -57,13 +57,33 @@ static inline void zend_objects_destroy_object(zend_object *object, zend_object_ zval_ptr_dtor(&destructor_func_name); zval_ptr_dtor(&retval_ptr); } +} + +static inline void zend_objects_destroy_object(zend_object *object, zend_object_handle handle TSRMLS_DC) +{ + zend_objects_call_destructor(object, handle TSRMLS_CC); /* Nuke the object */ zend_hash_destroy(object->properties); efree(object->properties); } + +void zend_objects_call_destructors(zend_objects *objects TSRMLS_DC) +{ + int i = 1; + + for (i = 0; i < objects->top ; i++) { + if (EG(objects).object_buckets[i].valid) { + EG(objects).object_buckets[i].constructor_called = 1; + zend_objects_destroy_object(&EG(objects).object_buckets[i].bucket.obj.object, i TSRMLS_CC); + EG(objects).object_buckets[i].valid = 0; + } + } +} + + zend_object_value zend_objects_new(zend_object **object, zend_class_entry *class_type) { zend_object_handle handle; diff --git a/Zend/zend_objects.h b/Zend/zend_objects.h index b649163007..f068afa8f7 100644 --- a/Zend/zend_objects.h +++ b/Zend/zend_objects.h @@ -25,6 +25,7 @@ typedef struct _zend_objects { } zend_objects; void zend_objects_init(zend_objects *objects, zend_uint init_size); +void zend_objects_call_destructors(zend_objects *objects TSRMLS_DC); void zend_objects_destroy(zend_objects *objects); zend_object_value zend_objects_new(zend_object **object, zend_class_entry *class_type); zend_object *zend_objects_get_address(zend_object_handle handle); diff --git a/Zend/zend_opcode.c b/Zend/zend_opcode.c index d79e0f7b22..85e5904b11 100644 --- a/Zend/zend_opcode.c +++ b/Zend/zend_opcode.c @@ -111,21 +111,21 @@ ZEND_API void destroy_zend_class(zend_class_entry *ce) } switch (ce->type) { case ZEND_USER_CLASS: + zend_hash_destroy(&ce->default_properties); + zend_hash_destroy(ce->static_members); efree(ce->name); efree(ce->refcount); zend_hash_destroy(&ce->function_table); - zend_hash_destroy(&ce->default_properties); - zend_hash_destroy(ce->static_members); - efree(ce->static_members); + FREE_HASHTABLE(ce->static_members); zend_hash_destroy(&ce->constants_table); zend_hash_destroy(&ce->class_table); break; case ZEND_INTERNAL_CLASS: + zend_hash_destroy(&ce->default_properties); + zend_hash_destroy(ce->static_members); free(ce->name); free(ce->refcount); zend_hash_destroy(&ce->function_table); - zend_hash_destroy(&ce->default_properties); - zend_hash_destroy(ce->static_members); free(ce->static_members); zend_hash_destroy(&ce->constants_table); zend_hash_destroy(&ce->class_table);