Skip to content

Commit 362e937

Browse files
committed
#53: * fix memory leak by resumed_coroutines logic
1 parent c365221 commit 362e937

File tree

3 files changed

+17
-7
lines changed

3 files changed

+17
-7
lines changed

coroutine.c

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -694,15 +694,17 @@ void async_coroutine_resume(zend_coroutine_t *coroutine, zend_object *error, con
694694
return;
695695
}
696696

697-
if (UNEXPECTED(circular_buffer_push(&ASYNC_G(coroutine_queue), &coroutine, true)) == FAILURE) {
697+
if (UNEXPECTED(circular_buffer_push_ptr_with_resize(&ASYNC_G(coroutine_queue), coroutine)) == FAILURE) {
698698
async_throw_error("Failed to enqueue coroutine");
699699
return;
700700
}
701701

702702
coroutine->waker->status = ZEND_ASYNC_WAKER_QUEUED;
703703

704704
// Add to resumed_coroutines queue for event cleanup
705-
circular_buffer_push(&ASYNC_G(resumed_coroutines), &coroutine, true);
705+
if (ZEND_ASYNC_IS_SCHEDULER_CONTEXT) {
706+
circular_buffer_push_ptr_with_resize(&ASYNC_G(resumed_coroutines), coroutine);
707+
}
706708
}
707709

708710
void async_coroutine_cancel(zend_coroutine_t *zend_coroutine,

internal/circular_buffer.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,10 @@ static zend_always_inline bool circular_buffer_is_not_empty(const circular_buffe
8787
return buffer->head != buffer->tail;
8888
}
8989

90+
static zend_always_inline void circular_buffer_clean(circular_buffer_t *buffer) {
91+
buffer->head = buffer->tail;
92+
}
93+
9094
/* Fast specialized version for pointer push (8 bytes) */
9195
static zend_always_inline zend_result circular_buffer_push_ptr(circular_buffer_t *buffer, void *ptr) {
9296
// Check if buffer is full using bitwise AND (capacity is power of 2)
@@ -121,4 +125,4 @@ static zend_always_inline zend_result circular_buffer_push_ptr_with_resize(circu
121125
return circular_buffer_push(buffer, &ptr, true);
122126
}
123127

124-
#endif // ASYNC_CIRCULAR_BUFFER_V2_H
128+
#endif // ASYNC_CIRCULAR_BUFFER_V2_H

scheduler.c

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1044,7 +1044,9 @@ void async_scheduler_coroutine_enqueue(zend_coroutine_t *coroutine)
10441044
coroutine->waker->status = ZEND_ASYNC_WAKER_QUEUED;
10451045

10461046
// Add to resumed_coroutines queue for event cleanup
1047-
circular_buffer_push_ptr_with_resize(&ASYNC_G(resumed_coroutines), coroutine);
1047+
if (ZEND_ASYNC_IS_SCHEDULER_CONTEXT) {
1048+
circular_buffer_push_ptr_with_resize(&ASYNC_G(resumed_coroutines), coroutine);
1049+
}
10481050
}
10491051

10501052
//
@@ -1074,11 +1076,11 @@ static zend_always_inline void scheduler_next_tick(void)
10741076

10751077
if (UNEXPECTED(current_time - ASYNC_G(last_reactor_tick) > REACTOR_CHECK_INTERVAL)) {
10761078
ASYNC_G(last_reactor_tick) = current_time;
1077-
const circular_buffer_t * queue = &ASYNC_G(coroutine_queue);
1079+
const circular_buffer_t *queue = &ASYNC_G(coroutine_queue);
10781080

10791081
has_handles = ZEND_ASYNC_REACTOR_EXECUTE(circular_buffer_is_not_empty(queue));
10801082

1081-
if (circular_buffer_is_not_empty(&ASYNC_G(resumed_coroutines))) {
1083+
if (circular_buffer_is_not_empty(&ASYNC_G(coroutine_queue))) {
10821084
process_resumed_coroutines();
10831085
}
10841086

@@ -1290,7 +1292,7 @@ ZEND_STACK_ALIGNED void fiber_entry(zend_fiber_transfer *transfer)
12901292
switch_status status = COROUTINE_NOT_EXISTS;
12911293

12921294
const circular_buffer_t *coroutine_queue = &ASYNC_G(coroutine_queue);
1293-
const circular_buffer_t *resumed_coroutines = &ASYNC_G(resumed_coroutines);
1295+
circular_buffer_t *resumed_coroutines = &ASYNC_G(resumed_coroutines);
12941296

12951297
do {
12961298

@@ -1303,6 +1305,8 @@ ZEND_STACK_ALIGNED void fiber_entry(zend_fiber_transfer *transfer)
13031305
execute_microtasks();
13041306
TRY_HANDLE_EXCEPTION();
13051307

1308+
ZEND_ASSERT(circular_buffer_is_not_empty(resumed_coroutines) == 0 && "resumed_coroutines should be 0");
1309+
13061310
has_next_coroutine = circular_buffer_count(coroutine_queue) > 0;
13071311
has_handles = ZEND_ASYNC_REACTOR_EXECUTE(has_next_coroutine);
13081312

0 commit comments

Comments
 (0)