Skip to content

Commit 4e69cd6

Browse files
committed
Implement yield state tracking for fiber coroutines and update cancellation logic
1 parent 6e05346 commit 4e69cd6

File tree

2 files changed

+17
-0
lines changed

2 files changed

+17
-0
lines changed

Zend/zend_async_API.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1062,6 +1062,7 @@ struct _zend_coroutine_s {
10621062
#define ZEND_COROUTINE_F_PROTECTED (1u << 13) /* coroutine is protected */
10631063
#define ZEND_COROUTINE_F_MAIN (1u << 14) /* coroutine is a main coroutine */
10641064
#define ZEND_COROUTINE_F_FIBER (1u << 15) /* coroutine is a fiber. extended_data -> fiber structure */
1065+
#define ZEND_COROUTINE_F_YIELD (1u << 16) /* coroutine is YIELD */
10651066

10661067
#define ZEND_COROUTINE_IS_ZOMBIE(coroutine) \
10671068
(((coroutine)->event.flags & ZEND_COROUTINE_F_ZOMBIE) != 0)
@@ -1095,6 +1096,12 @@ struct _zend_coroutine_s {
10951096
(((coroutine)->event.flags & ZEND_COROUTINE_F_FIBER) != 0)
10961097
#define ZEND_COROUTINE_SET_FIBER(coroutine) \
10971098
((coroutine)->event.flags |= ZEND_COROUTINE_F_FIBER)
1099+
#define ZEND_COROUTINE_IS_YIELD(coroutine) \
1100+
(((coroutine)->event.flags & ZEND_COROUTINE_F_YIELD) != 0)
1101+
#define ZEND_COROUTINE_SET_YIELD(coroutine) \
1102+
((coroutine)->event.flags |= ZEND_COROUTINE_F_YIELD)
1103+
#define ZEND_COROUTINE_CLR_YIELD(coroutine) \
1104+
((coroutine)->event.flags &= ~ZEND_COROUTINE_F_YIELD)
10981105

10991106
static zend_always_inline zend_string *zend_coroutine_callable_name(
11001107
const zend_coroutine_t *coroutine)

Zend/zend_fibers.c

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -921,6 +921,8 @@ static zend_result zend_fiber_yield(zend_fiber *fiber, zval *value, zval *return
921921
return FAILURE;
922922
}
923923

924+
ZEND_COROUTINE_SET_YIELD(fiber->coroutine);
925+
924926
ZEND_ASYNC_EVENT_CLR_EXCEPTION_HANDLED(&yield_event->base);
925927
ZEND_ASYNC_EVENT_SET_ZVAL_RESULT(&yield_event->base);
926928
ZEND_ASYNC_CALLBACKS_NOTIFY(&yield_event->base, value, NULL);
@@ -984,6 +986,8 @@ static void zend_fiber_resume_coroutine(zend_fiber *fiber, zval *value, zval *ex
984986
return;
985987
}
986988

989+
ZEND_COROUTINE_CLR_YIELD(fiber->coroutine);
990+
987991
// Wake up the fiber's coroutine
988992
if (UNEXPECTED(exception)) {
989993
ZEND_ASYNC_EVENT_CLR_ZVAL_RESULT(&fiber->resume_event->base);
@@ -1318,6 +1322,12 @@ static void zend_fiber_object_destroy(zend_object *object)
13181322

13191323
ZEND_ASYNC_CANCEL(coroutine, exception, true);
13201324

1325+
//
1326+
// A Fiber shares ownership of a coroutine with the Scheduler. This is important.
1327+
// When a coroutine is running, it belongs to the Scheduler, and its reference count must be greater than 1.
1328+
// The purpose of this code is to ensure that when a Fiber is destroyed,
1329+
// it correctly decrements the coroutine’s reference count without destroying the coroutine itself.
1330+
//
13211331
if (ZEND_COROUTINE_IS_STARTED(coroutine)) {
13221332
ZEND_ASYNC_EVENT_RELEASE(&coroutine->event);
13231333
}

0 commit comments

Comments
 (0)