Skip to content

Commit 0709578

Browse files
olsavmiccmb69
authored andcommitted
Fix GH-9266: GC root buffer keeps growing when dtors are present
Do not reset cleared count on GC rerun. Closes GH-9265.
1 parent c9fa98a commit 0709578

File tree

3 files changed

+64
-2
lines changed

3 files changed

+64
-2
lines changed

NEWS

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ PHP NEWS
55
- Core:
66
. Fixed --CGI-- support of run-tests.php. (cmb)
77
. Fixed incorrect double to long casting in latest clang. (zeriyoshi)
8+
. Fixed bug GH-9266 (GC root buffer keeps growing when dtors are present).
9+
(Michael Olšavský)
810

911
- Date:
1012
. Fixed bug GH-8730 (DateTime::diff miscalculation is same time zone of

Zend/tests/gc_045.phpt

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
--TEST--
2+
GC 045: Total count persisted when GC is rerun due to destructor call
3+
--INI--
4+
zend.enable_gc=1
5+
--FILE--
6+
<?php
7+
class GlobalData
8+
{
9+
public static Bar $bar;
10+
}
11+
12+
class Value
13+
{
14+
public function __destruct()
15+
{
16+
new Bar();
17+
}
18+
}
19+
20+
class Bar
21+
{
22+
public function __construct()
23+
{
24+
GlobalData::$bar = $this;
25+
}
26+
}
27+
28+
class Foo
29+
{
30+
public Foo $selfRef;
31+
public Value $val;
32+
33+
public function __construct(Value $val)
34+
{
35+
$this->val = $val;
36+
$this->selfRef = $this;
37+
}
38+
}
39+
40+
for ($j = 0; $j < 10; $j++) {
41+
for ($i = 0; $i < 3000; $i++) {
42+
new Foo(new Value());
43+
}
44+
}
45+
46+
var_dump(gc_status());
47+
?>
48+
--EXPECT--
49+
array(4) {
50+
["runs"]=>
51+
int(10)
52+
["collected"]=>
53+
int(25000)
54+
["threshold"]=>
55+
int(10001)
56+
["roots"]=>
57+
int(10000)
58+
}

Zend/zend_gc.c

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1439,12 +1439,13 @@ static void zend_gc_root_tmpvars(void);
14391439

14401440
ZEND_API int zend_gc_collect_cycles(void)
14411441
{
1442-
int count = 0;
1442+
int total_count = 0;
14431443
bool should_rerun_gc = 0;
14441444
bool did_rerun_gc = 0;
14451445

14461446
rerun_gc:
14471447
if (GC_G(num_roots)) {
1448+
int count;
14481449
gc_root_buffer *current, *last;
14491450
zend_refcounted *p;
14501451
uint32_t gc_flags = 0;
@@ -1622,6 +1623,7 @@ ZEND_API int zend_gc_collect_cycles(void)
16221623

16231624
GC_TRACE("Collection finished");
16241625
GC_G(collected) += count;
1626+
total_count += count;
16251627
GC_G(gc_active) = 0;
16261628
}
16271629

@@ -1638,7 +1640,7 @@ ZEND_API int zend_gc_collect_cycles(void)
16381640
finish:
16391641
zend_get_gc_buffer_release();
16401642
zend_gc_root_tmpvars();
1641-
return count;
1643+
return total_count;
16421644
}
16431645

16441646
ZEND_API void zend_gc_get_status(zend_gc_status *status)

0 commit comments

Comments
 (0)