Commit 5001116
Fix flaky AsyncContinuation cDAC dump test on osx-arm64 by using Task.Yield (#128004)
> [!NOTE]
> This pull request was prepared with assistance from GitHub Copilot.
## Problem
`AsyncContinuationDumpTests.ThreadLocalContinuation_IsContinuation`
fails intermittently on **osx-arm64 R2R** with:
> Could not find AsyncDispatcherInfo type in CoreLib
Failure tracked in #127774. Recently observed in builds
[1413917](https://dev.azure.com/dnceng-public/public/_build/results?buildId=1413917)
and
[1411121](https://dev.azure.com/dnceng-public/public/_build/results?buildId=1411121).
Fixes #127774
## Root cause
The test relies on the runtime having executed
`AsyncHelpers+RuntimeAsyncTask<T>.DispatchContinuations()`, which writes
`AsyncDispatcherInfo.t_current` and forces the JIT to load the
`AsyncDispatcherInfo` MethodTable.
The current debuggee uses `await Task.Delay(1)` to force a suspension.
On fast machines (in particular Apple Silicon CI machines) the 1ms timer
can fire before the runtime-async `Await` helper checks `IsCompleted`,
so the awaiter is observed as already-completed and the await runs
straight through synchronously. With no suspension there is no dispatch,
no `t_current` write, and the `AsyncDispatcherInfo` MT is never loaded.
I downloaded the failing osx-arm64 dump and walked the crashed thread:
```
[2-4] FailFast
[5] InnerAsync
[6] OuterAsync (async2 body)
[7] OuterAsync (thunk)
[8] Main
[9] CallEntryPoint
```
There is no `DispatchContinuations` frame on the stack. `OuterAsync`
calls `InnerAsync` directly, confirming the await did not suspend.
I also walked all 3 modules' `TypeDefToMethodTable` maps and confirmed
`AsyncDispatcherInfo` MT is genuinely null everywhere (i.e. cDAC is
reporting reality - the type never got loaded). `Object`, `Task`, and
`Continuation` MTs are all loaded as expected.
## Fix
Replace `await Task.Delay(1)` with `await Task.Yield()` in `InnerAsync`.
`Task.Yield()` returns a `YieldAwaitable` whose awaiter's `IsCompleted`
always returns `false`, so the continuation is unconditionally posted
back via `DispatchContinuations`. This guarantees
`AsyncDispatcherInfo.t_current` is written before `InnerAsync` resumes
and calls `FailFast`, regardless of machine timing.
## Validation
Posting as a draft to run CI across all platforms; the osx-arm64 R2R leg
is the one to watch.
Co-authored-by: Max Charlamb <maxcharlamb@microsoft.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>1 parent df032fb commit 5001116
1 file changed
Lines changed: 1 addition & 1 deletion
Lines changed: 1 addition & 1 deletion
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
18 | 18 | | |
19 | 19 | | |
20 | 20 | | |
21 | | - | |
| 21 | + | |
22 | 22 | | |
23 | 23 | | |
24 | 24 | | |
| |||
0 commit comments