Skip to content

fix: defer await_ready into await_suspend on affected MSVC builds - #469

Merged
sgerbino merged 1 commit into
cppalliance:developfrom
mvandeberg:fix/msvc-arm64-await-ready
Oct 23, 2026
Merged

sgerbino merged 1 commit into
cppalliance:developfrom
mvandeberg:fix/msvc-arm64-await-ready

Conversation

@mvandeberg

Copy link
Copy Markdown
Contributor

On MSVC 14.51 ARM64 release, the void-returning symmetric_transfer does not prevent every lost catch. With a call before a try, and an awaiter whose await_ready performs an atomic read-modify-write (as async_waker's does to consume a latched wakeup), a throw inside the try escaped the catch beside it and reached unhandled_exception. A plain or atomic load in await_ready did not trigger it, nor did anything tested on 14.44.

Where BOOST_CAPY_SYMMETRIC_TRANSFER_WORKAROUND is on, task's and quitter's transform_awaiter now report not ready, and ask the wrapped await_ready from inside await_suspend through the new detail::await_ready_then_suspend. It calls await_ready exactly once, since it may consume state, and returns false to continue without suspending when the awaitable is ready, so immediate completions do not grow the stack. Builds without the workaround are unchanged.

Add testCatchAfterRmwAwaitReady and testCatchAroundWakerWait. Correct the gate comments: the handle-return defect on ARM64 also reproduces on 19.44, where the 19.34-19.44 clause already covers it.

@cppalliance-bot

cppalliance-bot commented Oct 23, 2026 •

Copy link
Copy Markdown

An automated preview of the documentation is available at https://469.capy.prtest3.cppalliance.org/index.html

If more commits are pushed to the pull request, the docs will rebuild at the same URL.

2026-10-23 18:45:31 UTC

@cppalliance-bot

cppalliance-bot commented Oct 23, 2026 •

Copy link
Copy Markdown

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

Build time: 2026-10-23 19:06:41 UTC

@codecov

codecov Bot commented Oct 23, 2026 •

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 98.47%. Comparing base (6c2998a) to head (e1a78b3).

Additional details and impacted files

Impacted file tree graph

@@             Coverage Diff             @@
##           develop     #469      +/-   ##
===========================================
+ Coverage    98.36%   98.47%   +0.10%     
===========================================
  Files          137      137              
  Lines         7293     7293              
===========================================
+ Hits          7174     7182       +8     
+ Misses         119      111       -8     
Flag Coverage Δ
linux 98.46% <ø> (+0.08%) ⬆️

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

Files with missing lines Coverage Δ
include/boost/capy/detail/await_suspend_helper.hpp 100.00% <ø> (ø)
include/boost/capy/quitter.hpp 100.00% <ø> (ø)
include/boost/capy/task.hpp 100.00% <ø> (ø)

... and 7 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 6c2998a...e1a78b3. Read the comment docs.

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

On MSVC 14.51 ARM64 release, the void-returning symmetric_transfer
does not prevent every lost catch. With a call before a try, and an
awaiter whose await_ready performs an atomic read-modify-write (as
async_waker's does to consume a latched wakeup), a throw inside the
try escaped the catch beside it and reached unhandled_exception.
A plain or atomic load in await_ready did not trigger it, nor did
anything tested on 14.44.

Where BOOST_CAPY_SYMMETRIC_TRANSFER_WORKAROUND is on, task's and
quitter's transform_awaiter now report not ready, and ask the
wrapped await_ready from inside await_suspend through the new
detail::await_ready_then_suspend. It calls await_ready exactly once,
since it may consume state, and returns false to continue without
suspending when the awaitable is ready, so immediate completions do
not grow the stack. Builds without the workaround are unchanged.

Add regression tests: testCatchAfterRmwAwaitReady and
testCatchAroundWakerWait in task.cpp, and testCatchAfterRmwAwaitReady
and testCatchStopAfterRmwAwaitReady in quitter.cpp. Without the fix
all four fail on MSVC 14.51 ARM64 release and pass on ARM64 14.44,
x64 14.44 and x64 14.51. testVoidSuspendAwaitable covers the helper's
not-ready, void await_suspend branch.

Correct the gate comments: the handle-return defect on ARM64 also
reproduces on 19.44, where the 19.34-19.44 clause already covers it.
@mvandeberg
mvandeberg force-pushed the fix/msvc-arm64-await-ready branch from 1050a6b to e1a78b3 Compare October 23, 2026 18:42
@sgerbino
sgerbino merged commit eee4124 into cppalliance:develop Oct 23, 2026
41 checks passed
@github-project-automation github-project-automation Bot moved this from Backlog to Done in Beast2 Oct 23, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

3 participants