Repository navigation
test: make TimeoutHelperTests deterministic under thread-pool load - #7180
Conversation
…ays observes it The executionCompletesFirst=false path released the operation via a RunContinuationsAsynchronously TCS, so the operation's completion had to be scheduled on the thread pool within TimeoutHelper's 1s grace period. On a busy runner the grace timer won, the outcome was dropped, and InnerException was null. Run the continuation inline and assert the operation has completed before awaiting the helper. Fixes #7172
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
|
Warning Review limit reachedYou've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository. Next included review available in 16 minutes. View limit details
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info
📝 Walkthrough
Merge Risk: ⚪ Minimal · up to
|
[Low impact] The PR appears safe to merge; the stronger completion guard matches the test helper’s current callers. SummaryMakes
Reviews (2) · Last reviewed commit: "test: fail the timeout helper guard if t..." · Reviewed by Greptile |
ReviewThis is a test-only fix, and it looks correct. It removes the flake at its cause and doesn't add timeouts or retries.
I found no blocking issues. Approving from my side. |
|
Dispositions for the review findings (there are no inline threads):
Local check (net10.0): |
ReviewTest-only change. It looks correct and I have no blocking concerns.
Optional: the inline-continuation TCS is easy to change back to async by accident. The comment explains why it must stay inline, which is enough, so I'd leave it. LGTM. |
Summary
Before:
TimeoutHelperTests.Timeout_Preserves_Custom_Task_Cancellation(False)(and the otherexecutionCompletesFirst: falsecases) failed intermittently on loaded CI runners withExpected to be of type TaskCanceledException but Value is of type null.After: the released operation completes on the releasing thread before the test awaits
TimeoutHelper, so the result no longer depends on how busy the thread pool is.Cause
Timeout detection was already deterministic. The factory cancels
timeoutCtssynchronously, andTask.WhenAnyreturns the already-completed detection task. The race was in the step after that.TimeoutHelperthen waits up toTimeoutGracePeriod(1s) for the execution task so it can capture the exception to preserve. The test released the operation through aRunContinuationsAsynchronouslyTCS, which queued the continuation on the thread pool. When the pool was saturated, the grace-period timer fired before that work item ran.ObserveExceptionDuringGracePeriodAsyncthen found the task still incomplete and returnednull. The CI failure's 3.3s duration is consistent with this.I reproduced it locally by queuing 16x min-threads blocking work items and calling
SetResultfrom a non-pool thread. That gave the identical assertion failure.Fix
Test-only change in
ExecuteWithControlledTimeoutAsync:CompleteAfterReleaseAsyncuseConfigureAwait(false).SetResult()therefore runs the operation, and every operation in this file completes synchronously, before it returns.SetResult(). A future non-synchronous operation then fails clearly instead of flaking.There are no timeout increases or retries.
Tests run
TimeoutHelperTests.TimeoutHelperTestspassed 19/19 on net10.0 (3 runs) and on net8.0.TUnit.UnitTestssuite on net10.0 had 0 failures (612 total, 608 passed, 4 skipped).Fixes #7172
Summary by CodeRabbit