@@ -137,7 +137,7 @@ static zend_always_inline void switch_context(async_coroutine_t *coroutine, zend
137137
138138 // Transfer the exception to the current coroutine.
139139 if (UNEXPECTED (transfer .flags & ZEND_FIBER_TRANSFER_FLAG_ERROR )) {
140- zend_throw_exception_internal (Z_OBJ (transfer .value ));
140+ async_rethrow_exception (Z_OBJ (transfer .value ));
141141 ZVAL_NULL (& transfer .value );
142142 }
143143}
@@ -216,7 +216,7 @@ static switch_status execute_next_coroutine(zend_fiber_transfer *transfer)
216216 return COROUTINE_SWITCHED ;
217217 } else if (ZEND_ASYNC_CURRENT_COROUTINE == coroutine ) {
218218 if (error != NULL ) {
219- zend_throw_exception_internal (error );
219+ async_rethrow_exception (error );
220220 }
221221 return COROUTINE_SWITCHED ;
222222 } else {
@@ -637,6 +637,8 @@ void async_scheduler_launch(void)
637637 */
638638void async_scheduler_main_coroutine_suspend (void )
639639{
640+ bool do_bailout = false;
641+
640642 if (UNEXPECTED (ZEND_ASYNC_SCHEDULER == NULL )) {
641643 async_scheduler_launch ();
642644
@@ -648,6 +650,7 @@ void async_scheduler_main_coroutine_suspend(void)
648650 async_coroutine_t * coroutine = (async_coroutine_t * )ZEND_ASYNC_CURRENT_COROUTINE ;
649651 zend_fiber_transfer * transfer = ASYNC_G (main_transfer );
650652
653+ zend_try {
651654 // We reach this point when the main coroutine has completed its execution.
652655 async_coroutine_finalize (transfer , coroutine );
653656
@@ -668,6 +671,10 @@ void async_scheduler_main_coroutine_suspend(void)
668671
669672 switch_to_scheduler (NULL );
670673
674+ } zend_catch {
675+ do_bailout = true;
676+ } zend_end_try ();
677+
671678 ZEND_ASYNC_CURRENT_COROUTINE = NULL ;
672679 ZEND_ASSERT (ZEND_ASYNC_ACTIVE_COROUTINE_COUNT == 0 && "The active coroutine counter must be 1 at this point" );
673680 ZEND_ASYNC_DEACTIVATE ;
@@ -689,6 +696,13 @@ void async_scheduler_main_coroutine_suspend(void)
689696 zend_object * exit_exception = ZEND_ASYNC_EXIT_EXCEPTION ;
690697 ZEND_ASYNC_EXIT_EXCEPTION = NULL ;
691698
699+ if (UNEXPECTED (do_bailout )) {
700+ if (exit_exception != NULL ) {
701+ OBJ_RELEASE (exit_exception );
702+ }
703+ zend_bailout ();
704+ }
705+
692706 //
693707 // Before exiting completely, we rethrow the exit exception
694708 // that was raised somewhere in other coroutines.
@@ -697,7 +711,7 @@ void async_scheduler_main_coroutine_suspend(void)
697711 zend_exception_set_previous (EG (exception ), exit_exception );
698712 GC_DELREF (exit_exception );
699713 } else if (exit_exception != NULL ) {
700- zend_throw_exception_internal (exit_exception );
714+ async_rethrow_exception (exit_exception );
701715 }
702716}
703717
0 commit comments