mirror of
https://github.com/php/php-src.git
synced 2025-08-16 05:58:45 +02:00
Fixed bug #45434 (circular reference causes segfault in gc_collect_cycles())
This commit is contained in:
parent
8d2e0a7e0f
commit
0ab4c933e7
3 changed files with 28 additions and 11 deletions
|
@ -1,5 +1,5 @@
|
||||||
--TEST--
|
--TEST--
|
||||||
GC 028: GC and destructors
|
GC 029: GC and destructors
|
||||||
--FILE--
|
--FILE--
|
||||||
<?php
|
<?php
|
||||||
class Foo {
|
class Foo {
|
||||||
|
|
21
Zend/tests/gc_030.phpt
Normal file
21
Zend/tests/gc_030.phpt
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
--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
|
|
@ -553,9 +553,9 @@ ZEND_API int gc_collect_cycles(TSRMLS_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) {
|
||||||
|
|
||||||
EG(objects_store).object_buckets[Z_OBJ_HANDLE(p->z)].destructor_called = 1;
|
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.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.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--;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
count++;
|
count++;
|
||||||
|
@ -571,19 +571,15 @@ ZEND_API int gc_collect_cycles(TSRMLS_D)
|
||||||
EG(objects_store).object_buckets[Z_OBJ_HANDLE(p->z)].valid &&
|
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 <= 0) {
|
||||||
EG(objects_store).object_buckets[Z_OBJ_HANDLE(p->z)].bucket.obj.refcount = 1;
|
EG(objects_store).object_buckets[Z_OBJ_HANDLE(p->z)].bucket.obj.refcount = 1;
|
||||||
zend_try {
|
Z_TYPE(p->z) = IS_NULL;
|
||||||
Z_TYPE(p->z) = IS_NULL;
|
zend_objects_store_del_ref_by_handle(Z_OBJ_HANDLE(p->z) TSRMLS_CC);
|
||||||
zend_objects_store_del_ref_by_handle(Z_OBJ_HANDLE(p->z) TSRMLS_CC);
|
|
||||||
} zend_end_try();
|
|
||||||
}
|
}
|
||||||
} else if (Z_TYPE(p->z) == IS_ARRAY) {
|
} else if (Z_TYPE(p->z) == IS_ARRAY) {
|
||||||
Z_TYPE(p->z) = IS_NULL;
|
Z_TYPE(p->z) = IS_NULL;
|
||||||
zend_hash_destroy(Z_ARRVAL(p->z));
|
zend_hash_destroy(Z_ARRVAL(p->z));
|
||||||
FREE_HASHTABLE(Z_ARRVAL(p->z));
|
FREE_HASHTABLE(Z_ARRVAL(p->z));
|
||||||
} else {
|
} else {
|
||||||
zend_try {
|
zval_dtor(&p->z);
|
||||||
zval_dtor(&p->z);
|
|
||||||
} zend_end_try();
|
|
||||||
Z_TYPE(p->z) = IS_NULL;
|
Z_TYPE(p->z) = IS_NULL;
|
||||||
}
|
}
|
||||||
p = GC_G(next_to_free);
|
p = GC_G(next_to_free);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue