@@ -1032,18 +1032,17 @@ static void coroutine_entry_point(void)
10321032 }
10331033 zend_catch
10341034 {
1035- fiber -> flags |= ZEND_FIBER_FLAG_BAILOUT ;
10361035 is_bailout = true;
10371036 }
10381037 zend_end_try ();
10391038
10401039 zend_try
10411040 {
1042- zend_fiber_event * yield_event = fiber -> yield_event ;
1041+ fiber = coroutine -> extended_data ;
10431042 zend_async_event_t * yield_event_base = NULL ;
10441043
1045- if (yield_event ) {
1046- yield_event_base = & yield_event -> base ;
1044+ if (fiber && fiber -> yield_event ) {
1045+ yield_event_base = & fiber -> yield_event -> base ;
10471046 }
10481047
10491048 //
@@ -1095,14 +1094,19 @@ static void coroutine_entry_point(void)
10951094 }
10961095 zend_catch
10971096 {
1098- fiber -> flags |= ZEND_FIBER_FLAG_BAILOUT ;
10991097 is_bailout = true;
11001098 }
11011099 zend_end_try ();
11021100
1103- /* Cleanup callback and unset field to prevent GC / duplicate dtor issues. */
1104- zval_ptr_dtor (& fiber -> fci .function_name );
1105- ZVAL_UNDEF (& fiber -> fci .function_name );
1101+ if (fiber ) {
1102+ if (is_bailout ) {
1103+ fiber -> flags |= ZEND_FIBER_FLAG_BAILOUT ;
1104+ }
1105+
1106+ /* Cleanup callback and unset field to prevent GC / duplicate dtor issues. */
1107+ zval_ptr_dtor (& fiber -> fci .function_name );
1108+ ZVAL_UNDEF (& fiber -> fci .function_name );
1109+ }
11061110
11071111 if (is_bailout ) {
11081112 zend_bailout ();
@@ -1237,8 +1241,26 @@ static void zend_fiber_object_destroy(zend_object *object)
12371241 }
12381242
12391243 if (fiber -> coroutine != NULL ) {
1240- ZEND_ASYNC_EVENT_RELEASE (& fiber -> coroutine -> event );
1244+
1245+ //
1246+ // A situation is possible where a Fiber is destroyed earlier than the coroutine,
1247+ // while the coroutine is already running. In this case, we cancel the coroutine.
1248+ //
1249+ zend_coroutine_t * coroutine = fiber -> coroutine ;
12411250 fiber -> coroutine = NULL ;
1251+ coroutine -> extended_data = NULL ;
1252+
1253+ if (ZEND_COROUTINE_IS_FINISHED (coroutine )) {
1254+ ZEND_ASYNC_EVENT_RELEASE (& coroutine -> event );
1255+ return ;
1256+ }
1257+
1258+ zend_object * exception = zend_async_new_exception (
1259+ ZEND_ASYNC_EXCEPTION_CANCELLATION , "Fiber has been destroyed"
1260+ );
1261+
1262+ ZEND_ASYNC_CANCEL (coroutine , exception , true);
1263+
12421264 return ;
12431265 }
12441266
0 commit comments