- Fixed an issue in date() where a : was printed for the O modifier after a P
modifier was used. (Derick)
+- Fixed bug #45434 (circular reference causes segfault in gc_collect_cycles()).
+ (Dmitry)
- Fixed bug #44769 (declaring private magic methods should throw error). (Felipe)
- Fixed bug #44913 (Segfault when using return in combination with nested loops
and continue 2). (Dmitry)
--- /dev/null
+--TEST--
+GC 030: GC and exceptions in destructors
+--FILE--
+<?php
+class foo {
+ public $foo;
+
+ public function __destruct() {
+ throw new Exception("foobar");
+ }
+}
+
+$f1 = new foo;
+$f2 = new foo;
+$f1->foo = $f2;
+$f2->foo = $f1;
+unset($f1, $f2);
+gc_collect_cycles();
+?>
+--EXPECTF--
+Fatal error: Ignoring exception from foo::__destruct() while an exception is already active (Uncaught Exception in %sgc_030.php on line %d) in %sgc_030.php on line %d
!EG(objects_store).object_buckets[Z_OBJ_HANDLE(p->z)].destructor_called) {
EG(objects_store).object_buckets[Z_OBJ_HANDLE(p->z)].destructor_called = 1;
- zend_try {
- EG(objects_store).object_buckets[Z_OBJ_HANDLE(p->z)].bucket.obj.dtor(EG(objects_store).object_buckets[Z_OBJ_HANDLE(p->z)].bucket.obj.object, Z_OBJ_HANDLE(p->z) TSRMLS_CC);
- } zend_end_try();
+ EG(objects_store).object_buckets[Z_OBJ_HANDLE(p->z)].bucket.obj.refcount++;
+ EG(objects_store).object_buckets[Z_OBJ_HANDLE(p->z)].bucket.obj.dtor(EG(objects_store).object_buckets[Z_OBJ_HANDLE(p->z)].bucket.obj.object, Z_OBJ_HANDLE(p->z) TSRMLS_CC);
+ EG(objects_store).object_buckets[Z_OBJ_HANDLE(p->z)].bucket.obj.refcount--;
}
}
count++;
EG(objects_store).object_buckets[Z_OBJ_HANDLE(p->z)].valid &&
EG(objects_store).object_buckets[Z_OBJ_HANDLE(p->z)].bucket.obj.refcount <= 0) {
EG(objects_store).object_buckets[Z_OBJ_HANDLE(p->z)].bucket.obj.refcount = 1;
- zend_try {
- Z_TYPE(p->z) = IS_NULL;
- zend_objects_store_del_ref_by_handle(Z_OBJ_HANDLE(p->z) TSRMLS_CC);
- } zend_end_try();
+ Z_TYPE(p->z) = IS_NULL;
+ zend_objects_store_del_ref_by_handle(Z_OBJ_HANDLE(p->z) TSRMLS_CC);
}
} else if (Z_TYPE(p->z) == IS_ARRAY) {
Z_TYPE(p->z) = IS_NULL;
zend_hash_destroy(Z_ARRVAL(p->z));
FREE_HASHTABLE(Z_ARRVAL(p->z));
} else {
- zend_try {
- zval_dtor(&p->z);
- } zend_end_try();
+ zval_dtor(&p->z);
Z_TYPE(p->z) = IS_NULL;
}
p = GC_G(next_to_free);