Skip to content

[Interpreter] Raise a pending thread abort again at the resume point after a catch - #135939

Merged
jkotas merged 3 commits into
dotnet:mainfrom
pcshrosbree:interp-abort/abort-after-catch-resume-point
Oct 19, 2026
Merged

jkotas merged 3 commits into
dotnet:mainfrom
pcshrosbree:interp-abort/abort-after-catch-resume-point

Conversation

@pcshrosbree

Copy link
Copy Markdown
Contributor

Fixes #135463
Fixes #135871

This supersedes #135520, as @janvorli suggested there: the whole change in one PR, including the flip of the catch leave island.

I validated with Checked runtimes on linux-x64, osx-arm64 and windows-x64, built from main 24543dd with and without this PR. Both columns run this PR's tests; the main column runs them on main's runtime. The Regressions row is the exception: it compares each version's own runner. The results were the same on all three platforms.

main this PR
GitHub_135463, JIT pass, #135871 cases skipped pass, #135871 cases skipped
GitHub_135463, DOTNET_InterpMode 1/2/3, with and without TieredCompilation=0 process dies: assert in ReadyForAsyncException pass
GitHub_135530, the same six interpreter configurations fails (same assert) pass
ControlledExecutionTests (9 tests), JIT / InterpMode 1, 2, 3 9 pass / process dies (same assert) 9 pass / 9 pass
Regressions merged runner, JIT and the six interpreter configurations no new failures
JIT/interpreter, InterpMode 1 and 3 pass pass

GitHub_135463 needs both the flip and the change that marks the frame faulting: without the flip, the two #135871 cases fail; without marking the frame faulting, the abort is caught by the same handler again and again, and the test hangs.

Note

This PR was prepared with AI assistance (Anthropic Claude, checked by OpenAI Codex) at my request. I reviewed it before opening it.

When interpreted code catches a ThreadAbortException, raise the abort
again where the execution resumes after the catch, as
EECodeManager::ResumeAfterCatch does for compiled code:

- Set up Thread::m_OSContext for the resume point before calling
  COMPlusCheckForAbort, which expects its caller to do that (dotnet#135463).
- Dispatch the abort from a try block of its own, outside the C++ catch
  block for ResumeAfterCatchException, so that the execution can resume
  again when the abort is caught again in the same InterpExecMethod.
- Make the catch leave island the resume point. Within a leave, every
  edge into a catch leave island uses INTOP_LEAVE_CATCH; every other
  edge, including the final edge to the leave target, uses INTOP_BR.
  The catch therefore ends with INTOP_LEAVE_CATCH to its island. The
  island is inside every try region that encloses the catch's try
  region. The leave target need not be inside all of those regions
  (dotnet#135871).
- Mark the frame faulting before the dispatch, as INTOP_THROW does, so
  that the handlers are looked up at the resume IP itself rather than
  at the instruction before it.

Add the test GitHub_135463. Its two dotnet#135871 cases run only when the
test is interpreted, because jitted code gets them wrong until dotnet#135637
is fixed. Enable
ControlledExecutionTests.CancelInTryAndExitCatchNormally again, and stop
skipping test135530 under the interpreter.

Fixes dotnet#135463
Fixes dotnet#135871
@dotnet-policy-service dotnet-policy-service Bot added the community-contribution Indicates that the PR has been added by a community member label Oct 16, 2026
@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
Successfully started running 3 pipeline(s).
13 pipeline(s) were filtered out due to trigger conditions.
There may be pipelines that require an authorized user to comment /azp run to run.

@dotnet-policy-service

Copy link
Copy Markdown
Contributor

Tagging subscribers to this area: @JulieLeeMSFT, @BrzVlad, @janvorli
See info in area-owners.md if you want to be subscribed.

Comment thread src/coreclr/vm/interpexec.cpp Outdated
Comment thread src/coreclr/vm/interpexec.cpp Outdated
Remove the goto at the end of the catch of ResumeAfterCatchException,
which only jumped to the next statement. Move the block that raises the
abort again to just after the resume code, so that a pending abort
falls through into it instead of jumping to a label after EXIT_FRAME.
No change in behavior.
@pcshrosbree

Copy link
Copy Markdown
Contributor Author

For context, here is where the related thread-abort work stands:

Note

This comment was prepared with AI assistance (Anthropic Claude, checked by OpenAI Codex) at my request. I reviewed it before posting it.

@janvorli janvorli left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, thank you!

@pcshrosbree

Copy link
Copy Markdown
Contributor Author

@jkotas janvorli approved this, but Build Analysis is still red from the run on October 16. The CI failures I checked include:

  • HttpClient certificate tests on Linux and Android.
  • System.Threading test batches on browser-wasm and wasi-wasm.

JIT_r on browser-wasm checked matches the known issue #135966. Would you prefer a rerun, or /ba-g?

@jkotas
jkotas merged commit 40ed2da into dotnet:main Oct 19, 2026
129 of 131 checks passed
@pcshrosbree

Copy link
Copy Markdown
Contributor Author

Thank you for the review and the merge.

lewing pushed a commit that referenced this pull request Oct 20, 2026
…ormally (#136116)

> **TL;DR:** Since #135939 merged, `System.Runtime.Tests` times out in
browser-wasm CI. The likely cause is a test that needs threads but now
runs on single-threaded wasm, where it cannot finish. This one-line
change skips that test,
`ControlledExecutionTests.CancelInTryAndExitCatchNormally`, when threads
are unavailable, as the other `Task.Run` tests in its class do. This
PR's own browser CI run will show whether that resolves the timeout.

The test cancels its action from a `Task.Run` task while the action
spins. #135915 and #135939 merged a minute apart, and each changed this
class:

- #135915 moved `IsMultithreadingSupported` from the class onto the four
enabled tests that cancel from `Task.Run`.
- #135939 enabled `CancelInTryAndExitCatchNormally` again, but its
branch predated #135915, so on main the test has no such condition.

On single-threaded wasm, the canceling task cannot run while the action
spins. In the browser-wasm `LibraryTestsCoreCLR` leg,
`System.Runtime.Tests` had these results:

- Without #135939: passed in 872 s (build
[1641014](https://dev.azure.com/dnceng-public/public/_build/results?buildId=1641014))
and 972 s (build
[1641108](https://dev.azure.com/dnceng-public/public/_build/results?buildId=1641108)).
- With #135939: timed out at 5402 s in both builds
[1641112](https://dev.azure.com/dnceng-public/public/_build/results?buildId=1641112)
and
[1641117](https://dev.azure.com/dnceng-public/public/_build/results?buildId=1641117).

Under `src/libraries`, #135939 changed only this test's attribute. The
log does not name the test that was running.

Both PRs are mine, and I missed the interaction before they merged.

> [!NOTE]
> This PR was prepared with AI assistance (Anthropic Claude, checked by
OpenAI Codex) at my request. I reviewed it before posting it.
@dotnet-milestone-bot dotnet-milestone-bot Bot added this to the 12.0-preview1 milestone Oct 20, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area-CodeGen-Interpreter-coreclr community-contribution Indicates that the PR has been added by a community member

Projects

None yet

4 participants