Stop an attach's own replay landing in the middle of a test's frames #18

Merged
jaap-jan merged 1 commits from claude/fix-failed-test-3e1719 into main 2026-09-15 12:46:47 +00:00
Owner

TheClipboard_ReachesThePaneThatAskedForIt failed in CI on an opcode of 2 where it wanted 8 — a second SessionOpened frame where the clipboard's should have been. Only one thing sends a session a second SessionOpened, and that is ReplayAfterAttachAsync, the replay a reattaching page gets.

It arrives there because the replay is fired and forgotten from the socket-accept thread immediately after the attach is signalled, and the test helper returned on that signal. Deschedule the accept thread for a timeslice between the two — which a loaded CI box does — and the test opens its session first, so the replay finds that session live and sends it a replay-flagged SessionOpened after its real one.

Nothing is wrong with the workspace. The page treats a replay onto a pane it still has as idempotent, and ReplayAfterAttachAsync's own remarks already say racing a fresh page's first frames is harmless. What was wrong is a helper that waited for the attach and then let its callers count frames as though the attach were finished, so ConnectRendererAsync now waits for RendererReattached as well — raised as the last thing the replay does. The remark there argued a replay could not be sent early; it missed that it can be sent late, and now says so.

The same late replay could reset the credit window out from under ANewRenderer_ReplaysTheLiveSessionAndResetsItsCredits, which shares the helper, so that latent flake goes with it.

Verified by delaying the replay's snapshot by a millisecond: the old test fails under that, the fixed class passes it eight runs running. Without the delay, all 121 tests in the assembly pass.

`TheClipboard_ReachesThePaneThatAskedForIt` failed in CI on an opcode of 2 where it wanted 8 — a second `SessionOpened` frame where the clipboard's should have been. Only one thing sends a session a second `SessionOpened`, and that is `ReplayAfterAttachAsync`, the replay a reattaching page gets. It arrives there because the replay is fired and forgotten from the socket-accept thread immediately after the attach is signalled, and the test helper returned on that signal. Deschedule the accept thread for a timeslice between the two — which a loaded CI box does — and the test opens its session first, so the replay finds that session live and sends it a replay-flagged `SessionOpened` after its real one. Nothing is wrong with the workspace. The page treats a replay onto a pane it still has as idempotent, and `ReplayAfterAttachAsync`'s own remarks already say racing a fresh page's first frames is harmless. What was wrong is a helper that waited for the attach and then let its callers count frames as though the attach were finished, so `ConnectRendererAsync` now waits for `RendererReattached` as well — raised as the last thing the replay does. The remark there argued a replay could not be sent early; it missed that it can be sent late, and now says so. The same late replay could reset the credit window out from under `ANewRenderer_ReplaysTheLiveSessionAndResetsItsCredits`, which shares the helper, so that latent flake goes with it. Verified by delaying the replay's snapshot by a millisecond: the old test fails under that, the fixed class passes it eight runs running. Without the delay, all 121 tests in the assembly pass.
jaap-jan added 1 commit 2026-09-15 12:29:20 +00:00
Stop an attach's own replay landing in the middle of a test's frames
ci / build and test (pull_request) Successful in 7m43s
ci / desktop nightly (pull_request) Skipped
ci / api image (pull_request) Failing after 11s
ci / android head (pull_request) Successful in 8m7s
8e61fc72b4
TheClipboard_ReachesThePaneThatAskedForIt failed in CI on an opcode of 2
where it wanted 8: a second SessionOpened frame where the clipboard's
should have been. Only one thing sends a session a second SessionOpened,
and that is ReplayAfterAttachAsync, the replay a reattaching page gets.

It arrives there because the replay is fired and forgotten from the
socket-accept thread immediately after the attach is signalled, and the
test helper returned on that signal. Deschedule the accept thread for a
timeslice between the two -- which a loaded CI box does -- and the test
opens its session first, so the replay finds that session live and sends
it a replay-flagged SessionOpened after its real one.

Nothing is wrong with the workspace. The page treats a replay onto a pane
it still has as idempotent, and ReplayAfterAttachAsync's own remarks
already say racing a fresh page's first frames is harmless. What was
wrong is a helper that waited for the attach and then let its callers
count frames as though the attach were finished, so ConnectRendererAsync
now waits for RendererReattached as well -- raised as the last thing the
replay does. The remark there argued a replay could not be sent early; it
missed that it can be sent late, and now says so.

The same late replay could reset the credit window out from under
ANewRenderer_ReplaysTheLiveSessionAndResetsItsCredits, which shares the
helper, so that latent flake goes with it.

Verified by delaying the replay's snapshot by a millisecond: the old test
fails under that, and the fixed class passes it eight runs running.
jaap-jan merged commit 54bc142dce into main 2026-09-15 12:46:47 +00:00
Sign in to join this conversation.
No Reviewers
No labels
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: DodoTech-Public/DodoSSH#18