Skip to content

fix(ex): propagate handler exceptions out of run_async#314

Merged
sgerbino merged 1 commit into
cppalliance:developfrom
sgerbino:fix/run-async-handler-exceptions
Jun 15, 2026
Merged

fix(ex): propagate handler exceptions out of run_async#314
sgerbino merged 1 commit into
cppalliance:developfrom
sgerbino:fix/run-async-handler-exceptions

Conversation

@sgerbino

@sgerbino sgerbino commented Jun 15, 2026

Copy link
Copy Markdown
Collaborator

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.

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.
@cppalliance-bot

Copy link
Copy Markdown

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

@cppalliance-bot

Copy link
Copy Markdown

GCOVR code coverage report https://314.capy.prtest3.cppalliance.org/gcovr/index.html
LCOV code coverage report https://314.capy.prtest3.cppalliance.org/genhtml/index.html
Coverage Diff Report https://314.capy.prtest3.cppalliance.org/diff-report/index.html

Build time: 2026-06-15 18:30:05 UTC

@codecov

codecov Bot commented Jun 15, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 98.10%. Comparing base (7f2dc8e) to head (cdb01cb).
⚠️ Report is 4 commits behind head on develop.

Additional details and impacted files

Impacted file tree graph

@@           Coverage Diff            @@
##           develop     #314   +/-   ##
========================================
  Coverage    98.09%   98.10%           
========================================
  Files          164      164           
  Lines         8873     8896   +23     
========================================
+ Hits          8704     8727   +23     
  Misses         169      169           
Flag Coverage Δ
linux 98.19% <ø> (+<0.01%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

Files with missing lines Coverage Δ
include/boost/capy/detail/run_callbacks.hpp 100.00% <100.00%> (ø)
include/boost/capy/ex/run_async.hpp 100.00% <100.00%> (ø)

... and 10 files with indirect coverage changes


Continue to review full report in Codecov by Harness.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 7f2dc8e...cdb01cb. Read the comment docs.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@sgerbino sgerbino merged commit a66d738 into cppalliance:develop Jun 15, 2026
38 checks passed
@sgerbino sgerbino deleted the fix/run-async-handler-exceptions branch June 15, 2026 18:57
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

run_async behavior when handlers throw

2 participants