Skip to content

Wait for the fresh update check before counting it in the restore test - #188

Merged
Views2k merged 1 commit into
mainfrom
fix/update-check-restore-race
Nov 8, 2026
Merged

Views2k merged 1 commit into
mainfrom
fix/update-check-restore-race

Conversation

@Views2k

@Views2k Views2k commented Nov 8, 2026

Copy link
Copy Markdown
Owner

Today's scheduled nightly on main (run 42502266063, commit 8b1cee4) failed ApplicationUpdateCheckPolicyTests.RestoringDuringAnOldCheckRunsOneFreshCheckAfterTheOldResponseIsDiscarded with one check counted instead of two. The same code passed the nightly dispatched 15 hours earlier.

Cause, from the code. Restoring the updates feature control sets CanCheckApplicationUpdate while the old check still holds _applicationUpdateOperation. When the old response arrives on a thread-pool thread, the finally block of CheckApplicationUpdateAvailabilityAsync releases the operation slot first and only then restores the status and begins the fresh check. For that moment the controller looks idle: CanCheckApplicationUpdate is true, no operation is active, and one request has been counted. The test's WaitForCheckAsync polls exactly that idle condition every 10 ms, so a poll that lands in the window returns before the fresh request is counted and the next assertion sees 1. The window is microseconds long, which is why the failure is rare and appeared on a loaded runner during the full suite.

Change. Test only. The test now waits for the second request before it waits for the controller to go idle. The polling loop moved into a shared WaitUntilAsync helper; WaitForCheckAsync behaves the same for the other 32 tests in the class. Product code is unchanged.

Checked. Wisp.App.Tests built once and the ApplicationUpdateCheckPolicyTests class run once on the maintainer PC: 33 passed, 0 failed.

Not verified. The failure was not reproduced; that would need a delay injected into the controller's finally block. The diagnosis rests on reading the code and matches the recorded failure, including that the helper's own assertions did not fire. An alternative judged improbable: NetworkInterface.GetIsNetworkAvailable() returning false for the fresh check on the runner would give the same signature. #174 stays open until a scheduled nightly on main passes.

RestoringDuringAnOldCheckRunsOneFreshCheckAfterTheOldResponseIsDiscarded
failed once in the nightly suite with one check counted instead of two.
Restoring the updates feature sets CanCheckApplicationUpdate while the
old check is still running, and when the old response arrives, the
finally block of CheckApplicationUpdateAvailabilityAsync releases
_applicationUpdateOperation before it begins the fresh check. The old
response completes on another thread, so WaitForCheckAsync could poll
the controller in that window, find it idle, and return before the
fresh request was counted. The test now waits for the second request
before it waits for the controller to go idle.
@Views2k

Views2k commented Nov 8, 2026

Copy link
Copy Markdown
Owner Author

Full nightly dispatched on this branch (run 42505910128): the update-check test and the rest of the suite passed except WpfStyleRuntimeTests at the HUD host retry step, an unrelated intermittent failure diagnosed and fixed in #189. PR CI on this branch is green and the merge state is clean.

@Views2k
Views2k merged commit 58d4751 into main Nov 8, 2026
11 of 12 checks passed
@Views2k
Views2k deleted the fix/update-check-restore-race branch November 8, 2026 19:00
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.

1 participant