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 @@ -212,43 +212,30 @@ static zend_always_inline void clear_link_to_root(zend_generator *generator) {
212
212
}
213
213
}
214
214
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 */
217
216
static inline bool check_node_running_in_fiber (zend_generator * generator ) {
218
- ZEND_ASSERT (EG (flags ) & EG_FLAGS_IN_SHUTDOWN );
219
217
ZEND_ASSERT (generator -> execute_data );
220
218
221
- if (generator -> flags & ZEND_GENERATOR_IN_FIBER ) {
219
+ if (EXPECTED ( generator -> flags & ZEND_GENERATOR_IN_FIBER ) ) {
222
220
return true;
223
221
}
224
222
225
- if (generator -> node .children == 0 ) {
223
+ if (EXPECTED ( generator -> node .children == 0 ) ) {
226
224
return false;
227
225
}
228
226
229
- if (generator -> flags & ZEND_GENERATOR_DTOR_VISITED ) {
230
- return false;
231
- }
232
- generator -> flags |= ZEND_GENERATOR_DTOR_VISITED ;
233
-
234
227
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 );
239
229
}
240
230
241
231
zend_generator * child ;
242
232
ZEND_HASH_FOREACH_PTR (generator -> node .child .ht , child ) {
243
233
if (check_node_running_in_fiber (child )) {
244
- goto in_fiber ;
234
+ return true ;
245
235
}
246
236
} ZEND_HASH_FOREACH_END ();
247
- return false;
248
237
249
- in_fiber :
250
- generator -> flags |= ZEND_GENERATOR_IN_FIBER ;
251
- return true;
238
+ return false;
252
239
}
253
240
254
241
static void zend_generator_dtor_storage (zend_object * object ) /* {{{ */
Original file line number Diff line number Diff line change @@ -101,7 +101,6 @@ static const uint8_t ZEND_GENERATOR_FORCED_CLOSE = 0x2;
101
101
static const uint8_t ZEND_GENERATOR_AT_FIRST_YIELD = 0x4 ;
102
102
static const uint8_t ZEND_GENERATOR_DO_INIT = 0x8 ;
103
103
static const uint8_t ZEND_GENERATOR_IN_FIBER = 0x10 ;
104
- static const uint8_t ZEND_GENERATOR_DTOR_VISITED = 0x20 ;
105
104
106
105
void zend_register_generator_ce (void );
107
106
ZEND_API void zend_generator_close (zend_generator * generator , bool finished_execution );
You can’t perform that action at this time.
0 commit comments