fix(ex): terminate on an unhandled run_async exception#316
Conversation
The run_async trampoline's unhandled_exception swallowed every escaping exception, so an unhandled task error vanished silently and the documented "exceptions are rethrown" behavior never happened. Make the trampoline call std::terminate instead: an exception reaches it only by escaping a handler (a handler that threw, or the default handler on an otherwise-unhandled task error), which is a genuine fault with no owner to receive it. Failing fast is loud and leak-free (the process ends), and needs no executor cooperation. To observe an error instead, pass an error handler (it receives the exception_ptr); to catch one, co_await the work inside a coroutine. Cooperative cancellation must not be treated as a fault: the default handler discards a stop_requested_exception (quitter's stop sentinel) so a stopped quitter completes silently rather than terminating. The result-only handler delegates to the same logic. Document the new behavior and exclude the terminate lines from coverage. Add a POSIX fork-based death test covering both terminate paths (no handler, and a rethrowing handler); it is guarded out on Windows.
|
An automated preview of the documentation is available at https://316.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-16 13:57:05 UTC |
|
GCOVR code coverage report https://316.capy.prtest3.cppalliance.org/gcovr/index.html Build time: 2026-06-16 14:14:42 UTC |
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## develop #316 +/- ##
===========================================
- Coverage 98.09% 98.07% -0.03%
===========================================
Files 164 164
Lines 8873 8758 -115
===========================================
- Hits 8704 8589 -115
Misses 169 169
Flags with carried forward coverage won't be shown. Click here to find out more.
... and 6 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's unhandled_exception swallowed every escaping exception, so an unhandled task error vanished silently and the documented "exceptions are rethrown" behavior never happened.
Make the trampoline call std::terminate instead: an exception reaches it only by escaping a handler (a handler that threw, or the default handler on an otherwise-unhandled task error), which is a genuine fault with no owner to receive it. Failing fast is loud and leak-free (the process ends), and needs no executor cooperation. To observe an error instead, pass an error handler (it receives the exception_ptr); to catch one, co_await the work inside a coroutine.
Cooperative cancellation must not be treated as a fault: the default handler discards a stop_requested_exception (quitter's stop sentinel) so a stopped quitter completes silently rather than terminating. The result-only handler delegates to the same logic.
Document the new behavior and exclude the terminate lines from coverage. Add a POSIX fork-based death test covering both terminate paths (no handler, and a rethrowing handler); it is guarded out on Windows.