File tree 3 files changed +59
-20
lines changed
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) {
218
218
}
219
219
}
220
220
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 */
223
222
static inline bool check_node_running_in_fiber (zend_generator * generator ) {
224
- ZEND_ASSERT (EG (flags ) & EG_FLAGS_IN_SHUTDOWN );
225
223
ZEND_ASSERT (generator -> execute_data );
226
224
227
- if (generator -> flags & ZEND_GENERATOR_IN_FIBER ) {
225
+ if (EXPECTED ( generator -> flags & ZEND_GENERATOR_IN_FIBER ) ) {
228
226
return true;
229
227
}
230
228
231
- if (generator -> node .children == 0 ) {
229
+ if (EXPECTED ( generator -> node .children == 0 ) ) {
232
230
return false;
233
231
}
234
232
235
- if (generator -> flags & ZEND_GENERATOR_DTOR_VISITED ) {
236
- return false;
237
- }
238
- generator -> flags |= ZEND_GENERATOR_DTOR_VISITED ;
239
-
240
233
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 );
245
235
}
246
236
247
237
zend_generator * child ;
248
238
ZEND_HASH_FOREACH_PTR (generator -> node .child .ht , child ) {
249
239
if (check_node_running_in_fiber (child )) {
250
- goto in_fiber ;
240
+ return true ;
251
241
}
252
242
} ZEND_HASH_FOREACH_END ();
253
- return false;
254
243
255
- in_fiber :
256
- generator -> flags |= ZEND_GENERATOR_IN_FIBER ;
257
- return true;
244
+ return false;
258
245
}
259
246
260
247
static 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;
95
95
static const uint8_t ZEND_GENERATOR_AT_FIRST_YIELD = 0x4 ;
96
96
static const uint8_t ZEND_GENERATOR_DO_INIT = 0x8 ;
97
97
static const uint8_t ZEND_GENERATOR_IN_FIBER = 0x10 ;
98
- static const uint8_t ZEND_GENERATOR_DTOR_VISITED = 0x20 ;
99
98
100
99
void zend_register_generator_ce (void );
101
100
ZEND_API void zend_generator_close (zend_generator * generator , bool finished_execution );
You can’t perform that action at this time.
0 commit comments