Skip to content

[release/11.0] Fix generic virtual dispatch hang after multiple AssemblyLoadContext unloads - #133183

Open
github-actions[bot] wants to merge 1 commit into
release/11.0from
backport/pr-132859-to-release/11.0
Open

[release/11.0] Fix generic virtual dispatch hang after multiple AssemblyLoadContext unloads#133183
github-actions[bot] wants to merge 1 commit into
release/11.0from
backport/pr-132859-to-release/11.0

Conversation

@github-actions

@github-actions github-actions Bot commented Sep 3, 2026

Copy link
Copy Markdown
Contributor

Backport of #132859 to release/11.0

/cc @VSadov @copilot

Customer Impact

  • Customer reported
  • Found internally

#132562

the bug may cause permanent retention of unloadable types thus preventing unloading and causing hangs.

Regression

  • Yes
  • No

Root cause is the #89331 (net 8.0) and
it was exposed by #106843 (net 10.0)

Testing

There is a new targeted testcase that deterministically reproduces the issue.

Risk

Low. An off-by-one error allowed a type key be inserted into a sentinel cache (supposed to be always treated as full and replaced with larger real cache on an insertion).
Insertion into sentinel cache is by itself benign. Once that happens the sentinel is truly full and will resize on next insertion.

That is - except when the type first inserted was unloadable, then it cannot ever be unloaded.

The change fixes the part where we recognize sentinel cache correctly and always treat it as full.

…unloads (#132859)

- [x] Root cause confirmed: `GenericCache.TrySet` detected the flush
sentinel with `table.Length == 2`, but the sentinel array is length 3 (2
entries + element 0 used for aux data). The sentinel was therefore never
recognized, so after a flush entries were inserted into the *shared*
sentinel table. Since every flush re-installs that same sentinel, stale
entries survived flushes and generic-virtual-dispatch targets belonging
to unloaded collectible `AssemblyLoadContext`s could be returned once
native addresses were reused (hang/crash).
- [x] Fix in
`src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/GenericCache.cs`:
added `SENTINEL_TABLE_SIZE` constant and an `IsSentinel(table)` helper
based on `CacheElementCount(table)`, used by both sentinel checks in
`TrySet`; tightened the constructor assert.
- [x] Regression test added:
`src/tests/Loader/CollectibleAssemblies/GenericVirtualMethod` (payload
assembly with the generic virtual method/override from the issue +
runner that loads/invokes/unloads 10 times and asserts the
virtual-function-pointer cache is empty after each unload).
- [x] Validation: baseline `./build.sh clr+libs -lc release -rc checked`
(exit 0); test fails against unfixed CoreLib (cache entry version 2
after flush, exit 101) and passes with the fix (exit 100); other
`Loader/CollectibleAssemblies` tests still pass.

<!-- START COPILOT CODING AGENT SUFFIX -->

- Fixes #132562

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: VSadov <8218165+VSadov@users.noreply.github.com>
Co-authored-by: Vladimir Sadov <vsadov@microsoft.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
@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.

@VSadov
VSadov requested a review from EgorBo September 3, 2026 20:45
@VSadov VSadov added the Servicing-consider Issue for next servicing release review label Sep 3, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area-TypeSystem-coreclr Servicing-consider Issue for next servicing release review

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants