My question is regarding a passage in cppreference that I find confusing:
If the coroutine ends with an uncaught exception, it performs the following:
- catches the exception and calls promise.unhandled_exception() from within the catch-block
- calls promise.final_suspend() and co_awaits the result (e.g. to resume a continuation or publish a result). It's undefined behavior to resume a coroutine from this point.
(see https://en.cppreference.com/w/cpp/language/coroutines)
The second bullet point is what confuses me. They say final_suspend is intended to execute continuations, but then they say resuming a coroutine "from this point" is undefined behavior. That seems almost contradictory. What exactly is undefined behavior here? I can think of 3 scenarios:
resume
on a coroutine_handle in the body of final_suspend
?await_suspend
of the final awaiter?await_suspend
of the final awaiter?If one or all of these are undefined behavior, is that also true for final_suspend
after a return_void
or return_value
, or only after unhandled_exception
?
(I've created some sample code for scenario 3 on godbolt. It's not necessary for this question, but it might be helpful. Does my handling of exceptions and continuations produce undefined behavior in that example?)
coroutine_handle::resume
yields undefined behavior for any coroutine that is suspended at its final suspend point. This is always true of any coroutine so suspended.
Cppreference is simply pointing out that, in not catching an exception, the coroutine is considered suspended at its final suspend point.