Uh oh!
There was an error while loading. Please reload this page.
Fix async resumption stub with byref parameters - #129999
Conversation
It is not valid IL to initialize a byref local with `initobj`. Just load the value of these directly. We had a test for byref parameters, but it did not suspend and did not result in creation of a resumption stub. The test case requires suspension + NoInlining to guarantee a suspension point is created.
Tagging subscribers to this area: @agocke |
There was a problem hiding this comment.
Pull request overview
This PR fixes IL generation in the async resumption stub path to avoid emitting invalid IL for byref parameters, and adds a regression test that reliably exercises the resumption-stub creation path for out parameters by forcing an actual suspension.
Changes:
- Update
CEEJitInfo::getAsyncResumptionStubto avoidinitobjonbyreflocals by directly emitting a null managed pointer (ldc.0; conv.u) forbyrefarguments. - Strengthen the existing async/byref test by adding a suspension-producing scenario (and preventing inlining) so the runtime actually creates a resumption stub in the byref-parameter case.
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
| src/tests/async/byref-param/byref-param.cs | Adds a suspension-based byref/out test case to ensure a resumption stub is produced. |
| src/coreclr/vm/jitinterface.cpp | Fixes resumption-stub IL emission for byref parameters to avoid invalid initobj usage. |
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
jakobbotsch
commented
Jun 29, 2026
PTAL @VSadov |
wtgodbe
commented
Jun 29, 2026
We probably need this in p6 as well, aspnetcore sees the same test failures there |
jakobbotsch
commented
Jun 29, 2026
We can backport this to preview6 too, but as a workaround you can change |
wtgodbe
commented
Jun 29, 2026
Up to you on whether or not to backport, aspnetcore isn't actually blocked in p6, backflow there is purely for test verification |
…ionsGenerator tests The preview6 runtime miscompiles awaiting a synchronous Task-returning method that has a byref (out) parameter, throwing InvalidProgramException at runtime (dotnet/runtime#129999). Change ValidationsGeneratorTestBase.Verify to return Task<VerifyResult> instead of Task, which avoids the non-generic Task await path that triggers the bug. This is a preview6-only workaround; main ingests the real runtime fix. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Uh oh!
There was an error while loading. Please reload this page.
jakobbotsch
commented
Jun 30, 2026
/backport to release/11.0-preview6 |
Started backporting to |
…rs (#130022) Backport of #129999 to release/11.0-preview6 /cc @jakobbotsch ## Customer Impact - [X] Customer reported - [ ] Found internally A Task-returning method `A` with a byref parameter may cause the runtime to throw an `InvalidProgramException` if directly returning the result of another Task-returning method `B()`, the task returned by `B` suspends and also one of the following is true: - `A` is marked with `[MethodImpl(MethodImplOptions.NoInlining)]` - `B` returns `Task<T>` and `A` returns `Task` In these cases the runtime produces an internal IL stub with invalid IL. The invalid IL tries to zero a byref local using `initobj`, which is not legal IL. Reported by ASP.NET in #129990. ## Regression - [X] Yes - [ ] No This issue exists since runtime async was introduced, but #128384 made it possible to hit this issue from C# code. ## Testing Unit test introduced. ## Risk Low. Adjust IL emission to load a `byref` zero without `initobj`. --------- Co-authored-by: Jakob Botsch Nielsen <jakob.botsch.nielsen@gmail.com>
It is not valid IL to initialize a byref local with `initobj`. Just load the value of these directly. We had a test for byref parameters, but it did not suspend and did not result in creation of a resumption stub. The test case requires suspension + NoInlining to guarantee a suspension point is created.
It is not valid IL to initialize a byref local with
initobj. Just load the value of these directly.We had a test for byref parameters, but it did not suspend and did not result in creation of a resumption stub. The test case requires suspension + NoInlining to guarantee a suspension point is created.
In ASP.NET's case it is returning a
Task<VerifyResult>from aTaskreturning function. This also requires a suspension point and resumption stub.Fix#129990