]> granicus.if.org Git - php/commitdiff
Add additional stage to post-session cleanup.
authorStanislav Malyshev <stas@php.net>
Wed, 29 Jan 2003 17:54:48 +0000 (17:54 +0000)
committerStanislav Malyshev <stas@php.net>
Wed, 29 Jan 2003 17:54:48 +0000 (17:54 +0000)
We need separate cleanup stage because of the following problem:
Suppose we destroy class X, which destroys function table,
and in function table we have function foo() that has static $bar. Now if
object of class X was assigned to $bar, its destructor will be called and will
fail since X's function table is in mid-destruction.
So we want first of all to clean up all data and then move to tables
destruction.
Note that only run-time accessed data need to be cleaned up, pre-defined
data can not contain objects and thus are not probelmatic.
# Looks like we are having a lots of pain in the various parts of the body
# because of the destructors...

Zend/zend_compile.h
Zend/zend_execute_API.c
Zend/zend_opcode.c

index 8b676a6337f3ddbb8ee09e4d30c22806554949c0..5c61b76e5bb5b9dba5e6d3e0c639762b5e4fdacd 100644 (file)
@@ -427,6 +427,8 @@ ZEND_API void init_op_array(zend_op_array *op_array, zend_uchar type, int initia
 ZEND_API void destroy_op_array(zend_op_array *op_array);
 ZEND_API void zend_destroy_file_handle(zend_file_handle *file_handle TSRMLS_DC);
 ZEND_API void zend_file_handle_dtor(zend_file_handle *fh);
+ZEND_API int zend_cleanup_class_data(zend_class_entry **pce TSRMLS_DC);
+ZEND_API int zend_cleanup_function_data(zend_function *function TSRMLS_DC);
 
 ZEND_API void destroy_zend_function(zend_function *function);
 ZEND_API void destroy_zend_class(zend_class_entry **pce);
index c842ccc07f4c6d4a7b08a39382f6114bef9dabfb..6da53cacd07c7f753d169c02acab8d32a8f7c215 100644 (file)
@@ -218,6 +218,17 @@ void shutdown_executor(TSRMLS_D)
 
                zend_ptr_stack_destroy(&EG(argument_stack));
 
+               /* Cleanup static data for functions and arrays.
+                  We need separate cleanup stage because of the following problem:
+                  Suppose we destroy class X, which destroys function table,
+                  and in function table we have function foo() that has static $bar. Now if
+                  object of class X is assigned to $bar, its destructor will be called and will
+                  fail since X's function table is in mid-destruction.
+                  So we want first of all to clean up all data and then move to tables destruction.
+                  Note that only run-time accessed data need to be cleaned up, pre-defined data can
+                  not contain objects and thus are not probelmatic */
+               zend_hash_apply(EG(function_table), (apply_func_t) zend_cleanup_function_data);
+               zend_hash_apply(EG(class_table), (apply_func_t) zend_cleanup_class_data);
                /* Destroy all op arrays */
                if (EG(full_tables_cleanup)) {
                        zend_hash_apply(EG(function_table), (apply_func_t) is_not_internal_function TSRMLS_CC);
index 923061a04d5c69fe4f9736b403a70c0baece7531..05f4a7e9de5de7e5f61d6d9df9db6e29e40a2be3 100644 (file)
@@ -107,6 +107,33 @@ ZEND_API void destroy_zend_function(zend_function *function)
        }
 }
 
+static void zend_cleanup_op_array_data(zend_op_array *op_array)
+{
+       if (op_array->static_variables) {
+               zend_hash_clean(op_array->static_variables);
+       }
+}
+
+ZEND_API int zend_cleanup_function_data(zend_function *function TSRMLS_DC)
+{
+       if(function->type == ZEND_USER_FUNCTION) {
+               zend_cleanup_op_array_data((zend_op_array *) function);
+       }       
+       return 0;
+}
+
+ZEND_API int zend_cleanup_class_data(zend_class_entry **pce TSRMLS_DC)
+{
+       if((*pce)->type == ZEND_USER_CLASS) {
+               /* Clean all parts that can contain run-time data */
+               /* Note that only run-time accessed data need to be cleaned up, pre-defined data can
+                  not contain objects and thus are not probelmatic */
+               zend_hash_clean((*pce)->static_members);
+               zend_hash_apply(&(*pce)->class_table, (apply_func_t) zend_cleanup_class_data TSRMLS_CC);
+               zend_hash_apply(&(*pce)->function_table, (apply_func_t) zend_cleanup_function_data TSRMLS_CC);
+       }
+       return 0;
+}
 
 ZEND_API void destroy_zend_class(zend_class_entry **pce)
 {