Skip to content

Commit 9f57f11

Browse files
committed
#25: * fix Zend GC issue with Fiber case
1 parent bd76291 commit 9f57f11

File tree

1 file changed

+36
-11
lines changed

1 file changed

+36
-11
lines changed

Zend/zend_gc.c

Lines changed: 36 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2176,11 +2176,21 @@ ZEND_API int zend_gc_collect_cycles(void)
21762176
return 0;
21772177
}
21782178

2179+
const bool in_fiber = EG(active_fiber) != NULL;
2180+
21792181
//
21802182
// We might enter this context from different coroutines, so we don’t initialize anything here.
21812183
//
2182-
gc_async_context_t *context = &GC_G(async_context);
2183-
gc_stack *stack = GC_G(gc_stack);
2184+
gc_async_context_t *context = NULL;
2185+
gc_stack *stack = NULL;
2186+
2187+
if (in_fiber) {
2188+
context = emalloc(sizeof(gc_async_context_t));
2189+
stack = emalloc(sizeof(gc_stack));
2190+
} else {
2191+
context = &GC_G(async_context);
2192+
stack = GC_G(gc_stack);
2193+
}
21842194

21852195
if (UNEXPECTED(context->state == GC_ASYNC_STATE_CONTINUE)) {
21862196
// If we reach this point, it means the destructor call was interrupted by a suspend() operation,
@@ -2197,14 +2207,21 @@ ZEND_API int zend_gc_collect_cycles(void)
21972207
context->should_rerun_gc = 0;
21982208
context->did_rerun_gc = 0;
21992209
context->gc_flags = 0;
2210+
// reset the destructor index
2211+
GC_G(dtor_idx) = GC_FIRST_ROOT;
22002212

2201-
if (GC_G(gc_stack) == NULL) {
2202-
stack = ecalloc(1, sizeof(gc_stack));
2213+
if (false == in_fiber) {
2214+
if (GC_G(gc_stack) == NULL) {
2215+
stack = emalloc(sizeof(gc_stack));
2216+
stack->prev = NULL;
2217+
stack->next = NULL;
2218+
GC_G(gc_stack) = stack;
2219+
} else {
2220+
stack = GC_G(gc_stack);
2221+
}
2222+
} else {
22032223
stack->prev = NULL;
22042224
stack->next = NULL;
2205-
GC_G(gc_stack) = stack;
2206-
} else {
2207-
stack = GC_G(gc_stack);
22082225
}
22092226
}
22102227

@@ -2357,7 +2374,9 @@ ZEND_API int zend_gc_collect_cycles(void)
23572374
gc_stack_free(GC_COLLECT_STACK);
23582375

23592376
#ifdef PHP_ASYNC_API
2360-
end = GC_G(first_unused);
2377+
if (false == in_fiber) {
2378+
end = GC_G(first_unused);
2379+
}
23612380
#endif
23622381

23632382
/* Destroy zvals. The root buffer may be reallocated. */
@@ -2442,9 +2461,15 @@ ZEND_API int zend_gc_collect_cycles(void)
24422461

24432462
GC_G(collector_time) += zend_hrtime() - GC_COLLECT_START_TIME;
24442463
#ifdef PHP_ASYNC_API
2445-
GC_G(async_context).state = GC_ASYNC_STATE_NONE;
2446-
if (GC_G(gc_stack) != NULL) {
2447-
GC_COLLECT_FREE_STACK;
2464+
if (in_fiber) {
2465+
efree(context);
2466+
gc_stack_free(stack);
2467+
efree(stack);
2468+
} else {
2469+
GC_G(async_context).state = GC_ASYNC_STATE_NONE;
2470+
if (GC_G(gc_stack) != NULL) {
2471+
GC_COLLECT_FREE_STACK;
2472+
}
24482473
}
24492474
#endif
24502475
return GC_COLLECT_TOTAL_COUNT;

0 commit comments

Comments
 (0)