Skip to content

Commit bc317d3

Browse files
committed
Merge branch 'PHP-8.3' into PHP-8.4
* PHP-8.3: [ci skip] NEWS for GH-16025 [ci skip] NEWS for GH-16025 Fix assertion failure in generator dtor (#16025)
2 parents e4335ba + 26fd8d2 commit bc317d3

File tree

3 files changed

+59
-20
lines changed

3 files changed

+59
-20
lines changed

Zend/tests/gh15866.phpt

+53
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
--TEST--
2+
GH-15866: Core dumped in Zend/zend_generators.c
3+
--FILE--
4+
<?php
5+
6+
class Canary {
7+
public function __construct(public mixed $value) {}
8+
public function __destruct() {
9+
printf("%s\n", __METHOD__);
10+
}
11+
}
12+
13+
function g() {
14+
Fiber::suspend();
15+
}
16+
17+
function f($canary) {
18+
try {
19+
var_dump(yield from g());
20+
} finally {
21+
print "Generator finally\n";
22+
}
23+
}
24+
25+
$canary = new Canary(null);
26+
$iterable = f($canary);
27+
$fiber = new Fiber(function () use ($iterable, $canary) {
28+
try {
29+
$iterable->next();
30+
} finally {
31+
print "Fiber finally\n";
32+
}
33+
});
34+
$canary->value = $fiber;
35+
$fiber->start();
36+
37+
// Reset roots
38+
gc_collect_cycles();
39+
40+
// Add to roots, create garbage cycles
41+
$fiber = $iterable = $canary = null;
42+
43+
print "Collect cycles\n";
44+
gc_collect_cycles();
45+
46+
?>
47+
==DONE==
48+
--EXPECT--
49+
Collect cycles
50+
Canary::__destruct
51+
Generator finally
52+
Fiber finally
53+
==DONE==

Zend/zend_generators.c

+6-19
Original file line numberDiff line numberDiff line change
@@ -212,43 +212,30 @@ static zend_always_inline void clear_link_to_root(zend_generator *generator) {
212212
}
213213
}
214214

215-
/* In the context of zend_generator_dtor_storage during shutdown, check if
216-
* the intermediate node 'generator' is running in a fiber */
215+
/* Check if the node 'generator' is running in a fiber */
217216
static inline bool check_node_running_in_fiber(zend_generator *generator) {
218-
ZEND_ASSERT(EG(flags) & EG_FLAGS_IN_SHUTDOWN);
219217
ZEND_ASSERT(generator->execute_data);
220218

221-
if (generator->flags & ZEND_GENERATOR_IN_FIBER) {
219+
if (EXPECTED(generator->flags & ZEND_GENERATOR_IN_FIBER)) {
222220
return true;
223221
}
224222

225-
if (generator->node.children == 0) {
223+
if (EXPECTED(generator->node.children == 0)) {
226224
return false;
227225
}
228226

229-
if (generator->flags & ZEND_GENERATOR_DTOR_VISITED) {
230-
return false;
231-
}
232-
generator->flags |= ZEND_GENERATOR_DTOR_VISITED;
233-
234227
if (generator->node.children == 1) {
235-
if (check_node_running_in_fiber(generator->node.child.single)) {
236-
goto in_fiber;
237-
}
238-
return false;
228+
return check_node_running_in_fiber(generator->node.child.single);
239229
}
240230

241231
zend_generator *child;
242232
ZEND_HASH_FOREACH_PTR(generator->node.child.ht, child) {
243233
if (check_node_running_in_fiber(child)) {
244-
goto in_fiber;
234+
return true;
245235
}
246236
} ZEND_HASH_FOREACH_END();
247-
return false;
248237

249-
in_fiber:
250-
generator->flags |= ZEND_GENERATOR_IN_FIBER;
251-
return true;
238+
return false;
252239
}
253240

254241
static void zend_generator_dtor_storage(zend_object *object) /* {{{ */

Zend/zend_generators.h

-1
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,6 @@ static const uint8_t ZEND_GENERATOR_FORCED_CLOSE = 0x2;
101101
static const uint8_t ZEND_GENERATOR_AT_FIRST_YIELD = 0x4;
102102
static const uint8_t ZEND_GENERATOR_DO_INIT = 0x8;
103103
static const uint8_t ZEND_GENERATOR_IN_FIBER = 0x10;
104-
static const uint8_t ZEND_GENERATOR_DTOR_VISITED = 0x20;
105104

106105
void zend_register_generator_ce(void);
107106
ZEND_API void zend_generator_close(zend_generator *generator, bool finished_execution);

0 commit comments

Comments
 (0)