fix(ex): propagate handler exceptions out of run_async#314
Conversation
The run_async trampoline caught and discarded every exception in its unhandled_exception(), so an error handler that rethrew (and the default handler, which rethrows by design) had no way to surface a task failure. The documented "exceptions are rethrown" behavior never happened. Rethrow from the trampoline instead, so an exception escaping a handler propagates out of the call that resumes the task rather than being swallowed. A rethrowing unhandled_exception leaves the trampoline suspended at its final suspend point, so the suspend_never final_suspend never self-destroys the frame. Fire-and-forget launch has no later owner, so operator() reclaims the frame when the inline dispatch unwinds, before propagating. Cooperative cancellation is reported by quitter as a stop_requested_exception sentinel through the same exception() channel. That is a normal completion, not an error, so the default handler discards the sentinel and rethrows everything else; otherwise a stopped quitter with no error handler would terminate. The result-only handler delegates to the same logic. Add tests covering propagation through both trampoline allocators (default memory_resource and value allocator), a rethrowing error handler, and a stopped quitter under the default handler.
|
An automated preview of the documentation is available at https://314.capy.prtest3.cppalliance.org/index.html If more commits are pushed to the pull request, the docs will rebuild at the same URL. 2026-06-15 18:12:07 UTC |
|
GCOVR code coverage report https://314.capy.prtest3.cppalliance.org/gcovr/index.html Build time: 2026-06-15 18:30:05 UTC |
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## develop #314 +/- ##
========================================
Coverage 98.09% 98.10%
========================================
Files 164 164
Lines 8873 8896 +23
========================================
+ Hits 8704 8727 +23
Misses 169 169
Flags with carried forward coverage won't be shown. Click here to find out more.
... and 10 files with indirect coverage changes Continue to review full report in Codecov by Harness.
🚀 New features to boost your workflow:
|
Resolves #259.
The run_async trampoline caught and discarded every exception in its unhandled_exception(), so an error handler that rethrew (and the default handler, which rethrows by design) had no way to surface a task failure. The documented "exceptions are rethrown" behavior never happened.
Rethrow from the trampoline instead, so an exception escaping a handler propagates out of the call that resumes the task rather than being swallowed.
A rethrowing unhandled_exception leaves the trampoline suspended at its final suspend point, so the suspend_never final_suspend never self-destroys the frame. Fire-and-forget launch has no later owner, so operator() reclaims the frame when the inline dispatch unwinds, before propagating.
Cooperative cancellation is reported by quitter as a stop_requested_exception sentinel through the same exception() channel. That is a normal completion, not an error, so the default handler discards the sentinel and rethrows everything else; otherwise a stopped quitter with no error handler would terminate. The result-only handler delegates to the same logic.
Add tests covering propagation through both trampoline allocators (default memory_resource and value allocator), a rethrowing error handler, and a stopped quitter under the default handler.