From: Dmitry Stogov Date: Wed, 12 Jul 2006 07:54:00 +0000 (+0000) Subject: Fixed bug #36759 (Objects destructors are invoked in wrong order when script is finis... X-Git-Tag: php-5.2.0RC1~123 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=8bb047ee977936b10d8e415d18e9a82b87b0af15;p=php Fixed bug #36759 (Objects destructors are invoked in wrong order when script is finished). --- diff --git a/NEWS b/NEWS index 9c82673f9a..93be7adf05 100644 --- a/NEWS +++ b/NEWS @@ -171,6 +171,8 @@ PHP NEWS - Fixed bug #37244 (Added strict flag to base64_decode() that enforces RFC3548 compliance). (Ilia) - Fixed bug #36949 (invalid internal mysqli objects dtor). (Mike) +- Fixed bug #36759 (Objects destructors are invoked in wrong order when script + is finished). (Dmitry) - Fixed bug #36630 (umask not reset at the end of the request). (Ilia) - Fixed bug #35886 (file_get_contents() fails with some combinations of offset & maxlen). (Nuno) diff --git a/Zend/tests/bug36759.phpt b/Zend/tests/bug36759.phpt new file mode 100755 index 0000000000..8aa9977a06 --- /dev/null +++ b/Zend/tests/bug36759.phpt @@ -0,0 +1,27 @@ +--TEST-- +Bug #36759 (Objects destructors are invoked in wrong order when script is finished) +--FILE-- +bar = $bar; + } + function __destruct() { + echo __METHOD__,"\n"; + unset($this->bar); + } +} + +class Bar { + function __destruct() { + echo __METHOD__,"\n"; + unset($this->bar); + } +} +$y = new Bar(); +$x = new Foo($y); +?> +--EXPECT-- +Foo::__destruct +Bar::__destruct diff --git a/Zend/zend_execute_API.c b/Zend/zend_execute_API.c index 142cc0e371..4170a30e7c 100644 --- a/Zend/zend_execute_API.c +++ b/Zend/zend_execute_API.c @@ -190,8 +190,22 @@ void init_executor(TSRMLS_D) EG(This) = NULL; } +static int zval_call_destructor(zval **zv TSRMLS_DC) +{ + if (Z_TYPE_PP(zv) == IS_OBJECT && (*zv)->refcount == 1) { + return ZEND_HASH_APPLY_REMOVE; + } else { + return ZEND_HASH_APPLY_KEEP; + } +} + void shutdown_destructors(TSRMLS_D) { zend_try { + int symbols; + do { + symbols = zend_hash_num_elements(&EG(symbol_table)); + zend_hash_reverse_apply(&EG(symbol_table), (apply_func_t) zval_call_destructor TSRMLS_CC); + } while (symbols != zend_hash_num_elements(&EG(symbol_table))); zend_objects_store_call_destructors(&EG(objects_store) TSRMLS_CC); } zend_catch { /* if we couldn't destruct cleanly, mark all objects as destructed anyway */