File tree Expand file tree Collapse file tree 3 files changed +59
-20
lines changed Expand file tree Collapse file tree 3 files changed +59
-20
lines changed Original file line number Diff line number Diff line change 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==
Original file line number Diff line number Diff line change @@ -218,43 +218,30 @@ static zend_always_inline void clear_link_to_root(zend_generator *generator) {
218218 }
219219}
220220
221- /* In the context of zend_generator_dtor_storage during shutdown, check if
222- * the intermediate node 'generator' is running in a fiber */
221+ /* Check if the node 'generator' is running in a fiber */
223222static inline bool check_node_running_in_fiber (zend_generator * generator ) {
224- ZEND_ASSERT (EG (flags ) & EG_FLAGS_IN_SHUTDOWN );
225223 ZEND_ASSERT (generator -> execute_data );
226224
227- if (generator -> flags & ZEND_GENERATOR_IN_FIBER ) {
225+ if (EXPECTED ( generator -> flags & ZEND_GENERATOR_IN_FIBER ) ) {
228226 return true;
229227 }
230228
231- if (generator -> node .children == 0 ) {
229+ if (EXPECTED ( generator -> node .children == 0 ) ) {
232230 return false;
233231 }
234232
235- if (generator -> flags & ZEND_GENERATOR_DTOR_VISITED ) {
236- return false;
237- }
238- generator -> flags |= ZEND_GENERATOR_DTOR_VISITED ;
239-
240233 if (generator -> node .children == 1 ) {
241- if (check_node_running_in_fiber (generator -> node .child .single )) {
242- goto in_fiber ;
243- }
244- return false;
234+ return check_node_running_in_fiber (generator -> node .child .single );
245235 }
246236
247237 zend_generator * child ;
248238 ZEND_HASH_FOREACH_PTR (generator -> node .child .ht , child ) {
249239 if (check_node_running_in_fiber (child )) {
250- goto in_fiber ;
240+ return true ;
251241 }
252242 } ZEND_HASH_FOREACH_END ();
253- return false;
254243
255- in_fiber :
256- generator -> flags |= ZEND_GENERATOR_IN_FIBER ;
257- return true;
244+ return false;
258245}
259246
260247static void zend_generator_dtor_storage (zend_object * object ) /* {{{ */
Original file line number Diff line number Diff line change @@ -95,7 +95,6 @@ static const uint8_t ZEND_GENERATOR_FORCED_CLOSE = 0x2;
9595static const uint8_t ZEND_GENERATOR_AT_FIRST_YIELD = 0x4 ;
9696static const uint8_t ZEND_GENERATOR_DO_INIT = 0x8 ;
9797static const uint8_t ZEND_GENERATOR_IN_FIBER = 0x10 ;
98- static const uint8_t ZEND_GENERATOR_DTOR_VISITED = 0x20 ;
9998
10099void zend_register_generator_ce (void );
101100ZEND_API void zend_generator_close (zend_generator * generator , bool finished_execution );
You can’t perform that action at this time.
0 commit comments