Skip to content

Commit 9e80d3f

Browse files
committed
* Fixed GC behavior during coroutine cancellation when an exception occurs in the main coroutine while the GC is running.
1 parent 5dad0ed commit 9e80d3f

File tree

3 files changed

+57
-9
lines changed

3 files changed

+57
-9
lines changed

coroutine.c

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -343,7 +343,10 @@ zend_coroutine_t *async_new_coroutine(zend_async_scope_t *scope)
343343
{
344344
zend_object *object = coroutine_object_create(async_ce_coroutine);
345345

346-
if (UNEXPECTED(EG(exception))) {
346+
if (UNEXPECTED(object == NULL || EG(exception))) {
347+
if (object != NULL) {
348+
zend_object_release(object);
349+
}
347350
return NULL;
348351
}
349352

tests/gc/013-gc-fiber-destructors.phpt

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,6 @@ class Cycle {
1616
public function __destruct() {
1717
$id = self::$counter++;
1818
printf("%d: Start destruct\n", $id);
19-
if ($id === 0) {
20-
global $f2;
21-
$f2 = Fiber::getCurrent();
22-
Fiber::suspend(new stdClass);
23-
}
2419
printf("%d: End destruct\n", $id);
2520
}
2621
}
@@ -37,16 +32,14 @@ new Cycle();
3732
new Cycle();
3833
gc_collect_cycles();
3934

40-
$f2->resume();
41-
4235
?>
4336
--EXPECT--
4437
0: Start destruct
38+
0: End destruct
4539
1: Start destruct
4640
1: End destruct
4741
2: Start destruct
4842
2: End destruct
4943
3: Start destruct
5044
3: End destruct
51-
0: End destruct
5245
Shutdown
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
--TEST--
2+
Correct GC behavior when the main coroutine is destroyed due to an exception.
3+
--FILE--
4+
<?php
5+
6+
register_shutdown_function(function () {
7+
printf("Shutdown\n");
8+
});
9+
10+
class Cycle {
11+
public static $counter = 0;
12+
public $self;
13+
public function __construct() {
14+
$this->self = $this;
15+
}
16+
public function __destruct() {
17+
$id = self::$counter++;
18+
printf("%d: Start destruct\n", $id);
19+
printf("%d: End destruct\n", $id);
20+
}
21+
}
22+
23+
$f = new Fiber(function () {
24+
new Cycle();
25+
new Cycle();
26+
gc_collect_cycles();
27+
});
28+
29+
$f->start();
30+
31+
new Cycle();
32+
new Cycle();
33+
gc_collect_cycles();
34+
35+
throw new Exception("Trigger GC");
36+
37+
?>
38+
--EXPECTF--
39+
0: Start destruct
40+
0: End destruct
41+
1: Start destruct
42+
1: End destruct
43+
2: Start destruct
44+
2: End destruct
45+
3: Start destruct
46+
3: End destruct
47+
48+
Fatal error: Uncaught Exception: Trigger GC in %s:%d
49+
Stack trace:
50+
#0 {main}
51+
thrown in %s on line %d
52+
Shutdown

0 commit comments

Comments
 (0)