Skip to content

Commit 081883f

Browse files
committed
Rerun GC if destructors encountered
1 parent 0ce2359 commit 081883f

File tree

7 files changed

+14
-14
lines changed

7 files changed

+14
-14
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: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +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());
2322
?>
2423
--EXPECT--
2524
int(0)
26-
int(0)
2725
int(2)

Zend/zend_gc.c

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1430,7 +1430,10 @@ static void zend_get_gc_buffer_release(void);
14301430
ZEND_API int zend_gc_collect_cycles(void)
14311431
{
14321432
int count = 0;
1433+
zend_bool should_rerun_gc = 0;
1434+
zend_bool did_rerun_gc = 0;
14331435

1436+
rerun_gc:
14341437
if (GC_G(num_roots)) {
14351438
gc_root_buffer *current, *last;
14361439
zend_refcounted *p;
@@ -1475,8 +1478,8 @@ ZEND_API int zend_gc_collect_cycles(void)
14751478
* be introduced. These references can be introduced in a way that does not
14761479
* modify any refcounts, so we have no real way to detect this situation
14771480
* short of rerunning full GC tracing. What we do instead is to only run
1478-
* destructors at this point, and leave the actual freeing of the objects
1479-
* until the next GC run. */
1481+
* destructors at this point and automatically re-run GC afterwards. */
1482+
should_rerun_gc = 1;
14801483

14811484
/* Mark all roots for which a dtor will be invoked as DTOR_GARBAGE. Additionally
14821485
* color them purple. This serves a double purpose: First, they should be
@@ -1609,6 +1612,15 @@ ZEND_API int zend_gc_collect_cycles(void)
16091612
}
16101613

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

0 commit comments

Comments
 (0)