mirror of
https://github.com/php/php-src.git
synced 2024-11-23 01:44:06 +08:00
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)
This commit is contained in:
commit
bc317d3afc
53
Zend/tests/gh15866.phpt
Normal file
53
Zend/tests/gh15866.phpt
Normal file
@ -0,0 +1,53 @@
|
||||
--TEST--
|
||||
GH-15866: Core dumped in Zend/zend_generators.c
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
class Canary {
|
||||
public function __construct(public mixed $value) {}
|
||||
public function __destruct() {
|
||||
printf("%s\n", __METHOD__);
|
||||
}
|
||||
}
|
||||
|
||||
function g() {
|
||||
Fiber::suspend();
|
||||
}
|
||||
|
||||
function f($canary) {
|
||||
try {
|
||||
var_dump(yield from g());
|
||||
} finally {
|
||||
print "Generator finally\n";
|
||||
}
|
||||
}
|
||||
|
||||
$canary = new Canary(null);
|
||||
$iterable = f($canary);
|
||||
$fiber = new Fiber(function () use ($iterable, $canary) {
|
||||
try {
|
||||
$iterable->next();
|
||||
} finally {
|
||||
print "Fiber finally\n";
|
||||
}
|
||||
});
|
||||
$canary->value = $fiber;
|
||||
$fiber->start();
|
||||
|
||||
// Reset roots
|
||||
gc_collect_cycles();
|
||||
|
||||
// Add to roots, create garbage cycles
|
||||
$fiber = $iterable = $canary = null;
|
||||
|
||||
print "Collect cycles\n";
|
||||
gc_collect_cycles();
|
||||
|
||||
?>
|
||||
==DONE==
|
||||
--EXPECT--
|
||||
Collect cycles
|
||||
Canary::__destruct
|
||||
Generator finally
|
||||
Fiber finally
|
||||
==DONE==
|
@ -212,43 +212,30 @@ static zend_always_inline void clear_link_to_root(zend_generator *generator) {
|
||||
}
|
||||
}
|
||||
|
||||
/* In the context of zend_generator_dtor_storage during shutdown, check if
|
||||
* the intermediate node 'generator' is running in a fiber */
|
||||
/* Check if the node 'generator' is running in a fiber */
|
||||
static inline bool check_node_running_in_fiber(zend_generator *generator) {
|
||||
ZEND_ASSERT(EG(flags) & EG_FLAGS_IN_SHUTDOWN);
|
||||
ZEND_ASSERT(generator->execute_data);
|
||||
|
||||
if (generator->flags & ZEND_GENERATOR_IN_FIBER) {
|
||||
if (EXPECTED(generator->flags & ZEND_GENERATOR_IN_FIBER)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (generator->node.children == 0) {
|
||||
if (EXPECTED(generator->node.children == 0)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (generator->flags & ZEND_GENERATOR_DTOR_VISITED) {
|
||||
return false;
|
||||
}
|
||||
generator->flags |= ZEND_GENERATOR_DTOR_VISITED;
|
||||
|
||||
if (generator->node.children == 1) {
|
||||
if (check_node_running_in_fiber(generator->node.child.single)) {
|
||||
goto in_fiber;
|
||||
}
|
||||
return false;
|
||||
return check_node_running_in_fiber(generator->node.child.single);
|
||||
}
|
||||
|
||||
zend_generator *child;
|
||||
ZEND_HASH_FOREACH_PTR(generator->node.child.ht, child) {
|
||||
if (check_node_running_in_fiber(child)) {
|
||||
goto in_fiber;
|
||||
return true;
|
||||
}
|
||||
} ZEND_HASH_FOREACH_END();
|
||||
return false;
|
||||
|
||||
in_fiber:
|
||||
generator->flags |= ZEND_GENERATOR_IN_FIBER;
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
static void zend_generator_dtor_storage(zend_object *object) /* {{{ */
|
||||
|
@ -101,7 +101,6 @@ static const uint8_t ZEND_GENERATOR_FORCED_CLOSE = 0x2;
|
||||
static const uint8_t ZEND_GENERATOR_AT_FIRST_YIELD = 0x4;
|
||||
static const uint8_t ZEND_GENERATOR_DO_INIT = 0x8;
|
||||
static const uint8_t ZEND_GENERATOR_IN_FIBER = 0x10;
|
||||
static const uint8_t ZEND_GENERATOR_DTOR_VISITED = 0x20;
|
||||
|
||||
void zend_register_generator_ce(void);
|
||||
ZEND_API void zend_generator_close(zend_generator *generator, bool finished_execution);
|
||||
|
Loading…
Reference in New Issue
Block a user