Skip to content

Commit ae27297

Browse files
committed
Rerun GC if destructors encountered
1 parent d87b068 commit ae27297

File tree

7 files changed

+13
-12
lines changed

7 files changed

+13
-12
lines changed

Zend/tests/gc_011.phpt

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@ $a->a = $a;
1515
var_dump($a);
1616
unset($a);
1717
var_dump(gc_collect_cycles());
18-
var_dump(gc_collect_cycles());
1918
echo "ok\n"
2019
?>
2120
--EXPECTF--
@@ -24,6 +23,5 @@ object(Foo)#%d (1) {
2423
*RECURSION*
2524
}
2625
__destruct
27-
int(0)
2826
int(1)
2927
ok

Zend/tests/gc_016.phpt

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,9 @@ $a = new Foo();
1818
$a->a = $a;
1919
unset($a);
2020
var_dump(gc_collect_cycles());
21-
var_dump(gc_collect_cycles());
2221
echo "ok\n"
2322
?>
2423
--EXPECT--
2524
-> int(0)
26-
int(0)
2725
int(2)
2826
ok

Zend/tests/gc_017.phpt

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,13 +32,11 @@ unset($a);
3232
unset($b);
3333
unset($c);
3434
var_dump(gc_collect_cycles());
35-
var_dump(gc_collect_cycles());
3635
echo "ok\n"
3736
?>
3837
--EXPECTF--
3938
string(1) "%s"
4039
string(1) "%s"
4140
string(1) "%s"
42-
int(0)
4341
int(1)
4442
ok

Zend/tests/gc_028.phpt

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,6 @@ $bar->foo = $foo;
2828
unset($foo);
2929
unset($bar);
3030
var_dump(gc_collect_cycles());
31-
var_dump(gc_collect_cycles());
3231
?>
3332
--EXPECT--
34-
int(0)
3533
int(1)

Zend/tests/gc_029.phpt

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,6 @@ $bar->foo = $foo;
3030
unset($foo);
3131
unset($bar);
3232
var_dump(gc_collect_cycles());
33-
var_dump(gc_collect_cycles());
3433
?>
3534
--EXPECT--
36-
int(0)
3735
int(1)

Zend/tests/gc_035.phpt

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,7 @@ $a->x[] = $a;
1919
var_dump(gc_collect_cycles());
2020
unset($a);
2121
var_dump(gc_collect_cycles());
22-
var_dump(gc_collect_cycles());
22+
?>
2323
--EXPECT--
2424
int(0)
25-
int(0)
2625
int(2)

Zend/zend_gc.c

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1429,7 +1429,10 @@ static int gc_remove_nested_data_from_buffer(zend_refcounted *ref, gc_root_buffe
14291429
ZEND_API int zend_gc_collect_cycles(void)
14301430
{
14311431
int count = 0;
1432+
zend_bool should_rerun_gc = 0;
1433+
zend_bool did_rerun_gc = 0;
14321434

1435+
rerun_gc:
14331436
if (GC_G(num_roots)) {
14341437
gc_root_buffer *current, *last;
14351438
zend_refcounted *p;
@@ -1476,6 +1479,7 @@ ZEND_API int zend_gc_collect_cycles(void)
14761479
* short of rerunning full GC tracing. What we do instead is to only run
14771480
* destructors at this point, and leave the actual freeing of the objects
14781481
* until the next GC run. */
1482+
should_rerun_gc = 1;
14791483

14801484
/* Mark all roots for which a dtor will be invoked as DTOR_GARBAGE. Additionally
14811485
* color them purple. This serves a double purpose: First, they should be
@@ -1606,6 +1610,14 @@ ZEND_API int zend_gc_collect_cycles(void)
16061610

16071611
gc_compact();
16081612

1613+
/* Objects with destructors were removed from this GC run. Rerun GC right away to clean them
1614+
* up. We do this only once: If we encounter more destructors on the second run, we'll not
1615+
* run GC another time. */
1616+
if (should_rerun_gc && !did_rerun_gc) {
1617+
did_rerun_gc = 1;
1618+
goto rerun_gc;
1619+
}
1620+
16091621
return count;
16101622
}
16111623

0 commit comments

Comments
 (0)