Conversation
… attached before setValue/setException wrap each composed handler in try/catch, log and continue. attachThen/attachOnError's fire-now path, taken when the handler is attached after settlement, posted the handler bare, so a throwing handler escaped into the executor. Which path runs is a race between the producer settling and the consumer attaching; under ASan the backend thread settles first often enough that ladder's "Presenter::track() calls finishOne() even when onOk itself throws" failed on master (run 36115939775) with the throw escaping pumpUntil. Both fire-now closures now carry the same isolation. Two tests attach a throwing handler after settlement on the inline executor, which makes the race deterministic; both fail without the fix. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Y4eif7wQNNhSkHUKYqq5Xq
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What failed on master
The master CI run for
64d339aa(#809) failed one job, Application ladder / ASan+UBSan (run 36115939775):It has nothing to do with #809. The cause is in
include/morph/core/completion.hpp.Cause
CompletionStatedelivers a handler through one of two paths:setValue/setExceptionpost one composed closure. It wraps every handler in its owntry/catch, logs, and continues (completion.md, "Per-handler exception isolation").attachThen/attachOnErrorpost the handler through their fire-now closure without that wrapping, so a throw escapes into the executor. With Qt as the executor, it surfaced throughpumpUntil/processEvents.Which path runs is a race between the producer settling and the consumer attaching. The test comment already relies on the isolation ("Completion's executor ... itself catches (and logs) a throwing one rather than letting it escape to pumpUntil's caller"), and that held only when the attach won. ASan slows the attaching thread enough for the backend to settle first some of the time.
Fix
Both fire-now closures carry the same
try/catch+logErroras the composed closures.docs/spec/core/completion.mdnow states that isolation covers both paths.Verification
tests/test_completion_multi_handler.cppattach a throwingthen/onErrorhandler after settlement onInlineExecutor, which makes the race deterministic. Without the fix both fail (REQUIRE_NOTHROW(comp.then(...))→due to unexpected exception with message: handler blew up). With it,[completion]passes 78/78.kanban.BoardView keeps a usable board area and keeps every column reachable, fails identically on master locally and is not among the tests CI's ladder jobs run, so it is unrelated to this change and to the master CI failure.clang-tidy-diff.pyover the diff is clean, and a planted finding on a changed header line was reported, so the header lines are being analysed.clang-format22 is clean.Not verified: I did not reproduce the original ASan flake locally. The evidence that this is its cause is the stack of the failure (the handler's exception escaping the event loop) and the deterministic core reproduction above, not a before/after of the flaky ladder test itself. Re-open condition: the ladder test failing the same way with this change in.
🤖 Generated with Claude Code
https://claude.ai/code/session_01Y4eif7wQNNhSkHUKYqq5Xq