Clear RCW cache entries when releasing wrapper objects - #125754

Merged
jkoritzinsky merged 7 commits into
dotnet:mainfrom
jkoritzinsky:rcw-cache-clear
Mar 21, 2026
Merged

Clear RCW cache entries when releasing wrapper objects#125754
jkoritzinsky merged 7 commits into
dotnet:mainfrom
jkoritzinsky:rcw-cache-clear

Conversation

@jkoritzinsky

Copy link
Copy Markdown
Member

Remove native wrappers from the RCW cache in the tracker support global instance when releasing external objects for the Jupiter runtime. Without this change, a disconnected COM object wrapper could remain in the ComWrappers instance's cache. Then, if a new COM object is allocated at the same address (only possible because the COM objects were forcibly disconnected when ComWrappers.ReleaseObjects was called as part of the request from the Jupiter runtime), the old, disconnected COM object wrapper would be returned by ComWrappers.

Unblocks Microsoft Store migration to NativeAOT.

…al instance when releasing external objects for the Jupiter runtime
@jkoritzinskyjkoritzinsky added area-System.Runtime.InteropServices partner-impact This issue impacts a partner who needs to be kept updated labels Mar 18, 2026
@jkoritzinsky

Copy link
Copy Markdown
MemberAuthor

/backport to release/10.0

@github-actions

Copy link
Copy Markdown
Contributor

Started backporting to release/10.0 (link to workflow run)

@dotnet-policy-service

Copy link
Copy Markdown
Contributor

Tagging subscribers to this area: @dotnet/interop-contrib
See info in area-owners.md if you want to be subscribed.

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

This PR addresses a correctness issue in the reference-tracker (Jupiter) integration where RCW cache entries could outlive a forced disconnect, potentially causing ComWrappers to return a stale/disconnected wrapper if the native COM address is reused. This is particularly relevant for enabling NativeAOT scenarios that rely on ComWrappers.ReleaseObjects-driven disconnection.

Changes:

  • Track ReferenceTrackerNativeObjectWrapper instances released on thread-end and remove them from the RCW cache before calling ReleaseObjects.
  • Add an internal ComWrappers.RemoveWrappersFromCache(...) helper and a bulk-removal path in RcwCache.
  • Refactor RCW cache removal logic into a shared RemoveLocked(...) helper to avoid duplication.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.

FileDescription
src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/TrackerObjectManager.csCollects wrappers to remove during thread-end release and invokes RCW cache clearing before releasing objects.
src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/ComWrappers.csAdds an internal cache-removal API and implements bulk RCW cache removal with shared locked logic.

@jkoritzinsky

Copy link
Copy Markdown
MemberAuthor

/backport to release/10.0

@github-actions

Copy link
Copy Markdown
Contributor

Started backporting to release/10.0 (link to workflow run)

CopilotAI review requested due to automatic review settings March 19, 2026 20:59
@jkoritzinsky

Copy link
Copy Markdown
MemberAuthor

/backport to release/10.0

@github-actions

Copy link
Copy Markdown
Contributor

Started backporting to release/10.0 (link to workflow run)

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

This PR addresses a correctness issue in the COM tracker-support flow by ensuring RCW cache entries are cleared when external objects are released for the Jupiter runtime, preventing stale/disconnected wrappers from being returned if a COM object address is later reused.

Changes:

  • Remove eligible ReferenceTrackerNativeObjectWrapper instances from the global tracker-support ComWrappers RCW cache during ReleaseExternalObjectsFromCurrentThread.
  • Add ComWrappers/RcwCache APIs to remove multiple wrappers from the RCW cache in a single write-lock.
  • Add a regression test validating a new RCW is created after NotifyEndOfReferenceTrackingOnThread clears the cache.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 2 comments.

FileDescription
src/tests/Interop/COM/ComWrappers/GlobalInstance/GlobalInstance.csUpdates test harness behavior and adds a regression test for RCW cache clearing after thread-end notification.
src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/TrackerObjectManager.csCollects wrappers to remove and clears RCW cache entries during thread-end external object release.
src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/ComWrappers.csAdds bulk RCW cache removal support and refactors removal logic to share a locked helper.

Comment threadsrc/tests/Interop/COM/ComWrappers/GlobalInstance/GlobalInstance.cs Outdated
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
CopilotAI review requested due to automatic review settings March 19, 2026 23:22
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
@jkoritzinsky

Copy link
Copy Markdown
MemberAuthor

/backport to release/10.0

@github-actions

Copy link
Copy Markdown
Contributor

Started backporting to release/10.0 (link to workflow run)

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 3 out of 3 changed files in this pull request and generated 1 comment.

@jkoritzinsky

Copy link
Copy Markdown
MemberAuthor

/backport to release/10.0

@github-actions

Copy link
Copy Markdown
Contributor

Started backporting to release/10.0 (link to workflow run)

CopilotAI review requested due to automatic review settings March 20, 2026 17:47
@jkoritzinsky

Copy link
Copy Markdown
MemberAuthor

/backport to release/10.0

@github-actions

Copy link
Copy Markdown
Contributor

Started backporting to release/10.0 (link to workflow run)

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 3 out of 3 changed files in this pull request and generated 1 comment.

@jkoritzinsky

Copy link
Copy Markdown
MemberAuthor

/ba-g timeouts unrelated

@jkoritzinsky
jkoritzinsky merged commit ea02e22 into dotnet:mainMar 21, 2026
145 of 152 checks passed
JulieLeeMSFT pushed a commit that referenced this pull request Mar 23, 2026
…#125755)
Backport of #125754 to release/10.0
/cc @jkoritzinsky
## Customer Impact
- [X] Customer reported
- [X] Found internally
Found by the Microsoft Store team when they were working on migrating
PurchaseApp from .NET Native. Before this change, user code could
receive an invalid, cleared RCW from ComWrappers, resulting in
unexpected exceptions after any XAML thread has exited.
## Regression
- [X] Yes
- [ ] No
Technically a regression from .NET Core 3.1's built-in WinRT support and
.NET Native
## Testing
[How was the fix verified? How was the issue missed previously? What
tests were added?]
Added unit tests to validate the behavior. Also, the fix has been
validated internally
## Risk
[High/Medium/Low. Justify the indication by mentioning how risks were
measured and addressed.]
Low risk as this only kicks in in WinRT XAML scenarios and is not
observable for single-threaded WinRT XAML apps.
**IMPORTANT**: If this backport is for a servicing release, please
verify that:
- For .NET 8 and .NET 9: The PR target branch is `release/X.0-staging`,
not `release/X.0`.
- For .NET 10+: The PR target branch is `release/X.0` (no `-staging`
suffix).
## Package authoring no longer needed in .NET 9
**IMPORTANT**: Starting with .NET 9, you no longer need to edit a NuGet
package's csproj to enable building and bump the version.
Keep in mind that we still need package authoring in .NET 8 and older
versions.
---------
Co-authored-by: Jeremy Koritzinsky <jekoritz@microsoft.com>
Co-authored-by: Jeremy Koritzinsky <jkoritzinsky@gmail.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
@github-actionsgithub-actionsBot locked and limited conversation to collaborators Apr 20, 2026
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

area-System.Runtime.InteropServicespartner-impactThis issue impacts a partner who needs to be kept updated

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

4 participants

@jkoritzinsky@Sergio0694@AaronRobinsonMSFT
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

Clear RCW cache entries when releasing wrapper objects - #125754

Merged
jkoritzinsky merged 7 commits into
dotnet:mainfrom
jkoritzinsky:rcw-cache-clear
Mar 21, 2026
Merged

Clear RCW cache entries when releasing wrapper objects#125754
jkoritzinsky merged 7 commits into
dotnet:mainfrom
jkoritzinsky:rcw-cache-clear

Conversation

@jkoritzinsky

Copy link
Copy Markdown
Member

Remove native wrappers from the RCW cache in the tracker support global instance when releasing external objects for the Jupiter runtime. Without this change, a disconnected COM object wrapper could remain in the ComWrappers instance's cache. Then, if a new COM object is allocated at the same address (only possible because the COM objects were forcibly disconnected when ComWrappers.ReleaseObjects was called as part of the request from the Jupiter runtime), the old, disconnected COM object wrapper would be returned by ComWrappers.

Unblocks Microsoft Store migration to NativeAOT.

…al instance when releasing external objects for the Jupiter runtime
@jkoritzinskyjkoritzinsky added area-System.Runtime.InteropServices partner-impact This issue impacts a partner who needs to be kept updated labels Mar 18, 2026
@jkoritzinsky

Copy link
Copy Markdown
MemberAuthor

/backport to release/10.0

@github-actions

Copy link
Copy Markdown
Contributor

Started backporting to release/10.0 (link to workflow run)

@dotnet-policy-service

Copy link
Copy Markdown
Contributor

Tagging subscribers to this area: @dotnet/interop-contrib
See info in area-owners.md if you want to be subscribed.

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

This PR addresses a correctness issue in the reference-tracker (Jupiter) integration where RCW cache entries could outlive a forced disconnect, potentially causing ComWrappers to return a stale/disconnected wrapper if the native COM address is reused. This is particularly relevant for enabling NativeAOT scenarios that rely on ComWrappers.ReleaseObjects-driven disconnection.

Changes:

  • Track ReferenceTrackerNativeObjectWrapper instances released on thread-end and remove them from the RCW cache before calling ReleaseObjects.
  • Add an internal ComWrappers.RemoveWrappersFromCache(...) helper and a bulk-removal path in RcwCache.
  • Refactor RCW cache removal logic into a shared RemoveLocked(...) helper to avoid duplication.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.

FileDescription
src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/TrackerObjectManager.csCollects wrappers to remove during thread-end release and invokes RCW cache clearing before releasing objects.
src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/ComWrappers.csAdds an internal cache-removal API and implements bulk RCW cache removal with shared locked logic.

@jkoritzinsky

Copy link
Copy Markdown
MemberAuthor

/backport to release/10.0

@github-actions

Copy link
Copy Markdown
Contributor

Started backporting to release/10.0 (link to workflow run)

CopilotAI review requested due to automatic review settings March 19, 2026 20:59
@jkoritzinsky

Copy link
Copy Markdown
MemberAuthor

/backport to release/10.0

@github-actions

Copy link
Copy Markdown
Contributor

Started backporting to release/10.0 (link to workflow run)

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

This PR addresses a correctness issue in the COM tracker-support flow by ensuring RCW cache entries are cleared when external objects are released for the Jupiter runtime, preventing stale/disconnected wrappers from being returned if a COM object address is later reused.

Changes:

  • Remove eligible ReferenceTrackerNativeObjectWrapper instances from the global tracker-support ComWrappers RCW cache during ReleaseExternalObjectsFromCurrentThread.
  • Add ComWrappers/RcwCache APIs to remove multiple wrappers from the RCW cache in a single write-lock.
  • Add a regression test validating a new RCW is created after NotifyEndOfReferenceTrackingOnThread clears the cache.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 2 comments.

FileDescription
src/tests/Interop/COM/ComWrappers/GlobalInstance/GlobalInstance.csUpdates test harness behavior and adds a regression test for RCW cache clearing after thread-end notification.
src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/TrackerObjectManager.csCollects wrappers to remove and clears RCW cache entries during thread-end external object release.
src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/ComWrappers.csAdds bulk RCW cache removal support and refactors removal logic to share a locked helper.

Comment threadsrc/tests/Interop/COM/ComWrappers/GlobalInstance/GlobalInstance.cs Outdated
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
CopilotAI review requested due to automatic review settings March 19, 2026 23:22
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
@jkoritzinsky

Copy link
Copy Markdown
MemberAuthor

/backport to release/10.0

@github-actions

Copy link
Copy Markdown
Contributor

Started backporting to release/10.0 (link to workflow run)

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 3 out of 3 changed files in this pull request and generated 1 comment.

@jkoritzinsky

Copy link
Copy Markdown
MemberAuthor

/backport to release/10.0

@github-actions

Copy link
Copy Markdown
Contributor

Started backporting to release/10.0 (link to workflow run)

CopilotAI review requested due to automatic review settings March 20, 2026 17:47
@jkoritzinsky

Copy link
Copy Markdown
MemberAuthor

/backport to release/10.0

@github-actions

Copy link
Copy Markdown
Contributor

Started backporting to release/10.0 (link to workflow run)

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 3 out of 3 changed files in this pull request and generated 1 comment.

@jkoritzinsky

Copy link
Copy Markdown
MemberAuthor

/ba-g timeouts unrelated

@jkoritzinsky
jkoritzinsky merged commit ea02e22 into dotnet:mainMar 21, 2026
145 of 152 checks passed
JulieLeeMSFT pushed a commit that referenced this pull request Mar 23, 2026
…#125755)
Backport of #125754 to release/10.0
/cc @jkoritzinsky
## Customer Impact
- [X] Customer reported
- [X] Found internally
Found by the Microsoft Store team when they were working on migrating
PurchaseApp from .NET Native. Before this change, user code could
receive an invalid, cleared RCW from ComWrappers, resulting in
unexpected exceptions after any XAML thread has exited.
## Regression
- [X] Yes
- [ ] No
Technically a regression from .NET Core 3.1's built-in WinRT support and
.NET Native
## Testing
[How was the fix verified? How was the issue missed previously? What
tests were added?]
Added unit tests to validate the behavior. Also, the fix has been
validated internally
## Risk
[High/Medium/Low. Justify the indication by mentioning how risks were
measured and addressed.]
Low risk as this only kicks in in WinRT XAML scenarios and is not
observable for single-threaded WinRT XAML apps.
**IMPORTANT**: If this backport is for a servicing release, please
verify that:
- For .NET 8 and .NET 9: The PR target branch is `release/X.0-staging`,
not `release/X.0`.
- For .NET 10+: The PR target branch is `release/X.0` (no `-staging`
suffix).
## Package authoring no longer needed in .NET 9
**IMPORTANT**: Starting with .NET 9, you no longer need to edit a NuGet
package's csproj to enable building and bump the version.
Keep in mind that we still need package authoring in .NET 8 and older
versions.
---------
Co-authored-by: Jeremy Koritzinsky <jekoritz@microsoft.com>
Co-authored-by: Jeremy Koritzinsky <jkoritzinsky@gmail.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
@github-actionsgithub-actionsBot locked and limited conversation to collaborators Apr 20, 2026
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

area-System.Runtime.InteropServicespartner-impactThis issue impacts a partner who needs to be kept updated

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

4 participants

@jkoritzinsky@Sergio0694@AaronRobinsonMSFT
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Clear RCW cache entries when releasing wrapper objects - #125754

Merged
jkoritzinsky merged 7 commits into
dotnet:mainfrom
jkoritzinsky:rcw-cache-clear
Mar 21, 2026
Merged

Clear RCW cache entries when releasing wrapper objects#125754
jkoritzinsky merged 7 commits into
dotnet:mainfrom
jkoritzinsky:rcw-cache-clear

Conversation

@jkoritzinsky

Copy link
Copy Markdown
Member

Remove native wrappers from the RCW cache in the tracker support global instance when releasing external objects for the Jupiter runtime. Without this change, a disconnected COM object wrapper could remain in the ComWrappers instance's cache. Then, if a new COM object is allocated at the same address (only possible because the COM objects were forcibly disconnected when ComWrappers.ReleaseObjects was called as part of the request from the Jupiter runtime), the old, disconnected COM object wrapper would be returned by ComWrappers.

Unblocks Microsoft Store migration to NativeAOT.

…al instance when releasing external objects for the Jupiter runtime
@jkoritzinskyjkoritzinsky added area-System.Runtime.InteropServices partner-impact This issue impacts a partner who needs to be kept updated labels Mar 18, 2026
@jkoritzinsky

Copy link
Copy Markdown
MemberAuthor

/backport to release/10.0

@github-actions

Copy link
Copy Markdown
Contributor

Started backporting to release/10.0 (link to workflow run)

@dotnet-policy-service

Copy link
Copy Markdown
Contributor

Tagging subscribers to this area: @dotnet/interop-contrib
See info in area-owners.md if you want to be subscribed.

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

This PR addresses a correctness issue in the reference-tracker (Jupiter) integration where RCW cache entries could outlive a forced disconnect, potentially causing ComWrappers to return a stale/disconnected wrapper if the native COM address is reused. This is particularly relevant for enabling NativeAOT scenarios that rely on ComWrappers.ReleaseObjects-driven disconnection.

Changes:

  • Track ReferenceTrackerNativeObjectWrapper instances released on thread-end and remove them from the RCW cache before calling ReleaseObjects.
  • Add an internal ComWrappers.RemoveWrappersFromCache(...) helper and a bulk-removal path in RcwCache.
  • Refactor RCW cache removal logic into a shared RemoveLocked(...) helper to avoid duplication.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.

FileDescription
src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/TrackerObjectManager.csCollects wrappers to remove during thread-end release and invokes RCW cache clearing before releasing objects.
src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/ComWrappers.csAdds an internal cache-removal API and implements bulk RCW cache removal with shared locked logic.

@jkoritzinsky

Copy link
Copy Markdown
MemberAuthor

/backport to release/10.0

@github-actions

Copy link
Copy Markdown
Contributor

Started backporting to release/10.0 (link to workflow run)

CopilotAI review requested due to automatic review settings March 19, 2026 20:59
@jkoritzinsky

Copy link
Copy Markdown
MemberAuthor

/backport to release/10.0

@github-actions

Copy link
Copy Markdown
Contributor

Started backporting to release/10.0 (link to workflow run)

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

This PR addresses a correctness issue in the COM tracker-support flow by ensuring RCW cache entries are cleared when external objects are released for the Jupiter runtime, preventing stale/disconnected wrappers from being returned if a COM object address is later reused.

Changes:

  • Remove eligible ReferenceTrackerNativeObjectWrapper instances from the global tracker-support ComWrappers RCW cache during ReleaseExternalObjectsFromCurrentThread.
  • Add ComWrappers/RcwCache APIs to remove multiple wrappers from the RCW cache in a single write-lock.
  • Add a regression test validating a new RCW is created after NotifyEndOfReferenceTrackingOnThread clears the cache.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 2 comments.

FileDescription
src/tests/Interop/COM/ComWrappers/GlobalInstance/GlobalInstance.csUpdates test harness behavior and adds a regression test for RCW cache clearing after thread-end notification.
src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/TrackerObjectManager.csCollects wrappers to remove and clears RCW cache entries during thread-end external object release.
src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/ComWrappers.csAdds bulk RCW cache removal support and refactors removal logic to share a locked helper.

Comment threadsrc/tests/Interop/COM/ComWrappers/GlobalInstance/GlobalInstance.cs Outdated
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
CopilotAI review requested due to automatic review settings March 19, 2026 23:22
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
@jkoritzinsky

Copy link
Copy Markdown
MemberAuthor

/backport to release/10.0

@github-actions

Copy link
Copy Markdown
Contributor

Started backporting to release/10.0 (link to workflow run)

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 3 out of 3 changed files in this pull request and generated 1 comment.

@jkoritzinsky

Copy link
Copy Markdown
MemberAuthor

/backport to release/10.0

@github-actions

Copy link
Copy Markdown
Contributor

Started backporting to release/10.0 (link to workflow run)

CopilotAI review requested due to automatic review settings March 20, 2026 17:47
@jkoritzinsky

Copy link
Copy Markdown
MemberAuthor

/backport to release/10.0

@github-actions

Copy link
Copy Markdown
Contributor

Started backporting to release/10.0 (link to workflow run)

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 3 out of 3 changed files in this pull request and generated 1 comment.

@jkoritzinsky

Copy link
Copy Markdown
MemberAuthor

/ba-g timeouts unrelated

@jkoritzinsky
jkoritzinsky merged commit ea02e22 into dotnet:mainMar 21, 2026
145 of 152 checks passed
JulieLeeMSFT pushed a commit that referenced this pull request Mar 23, 2026
…#125755)
Backport of #125754 to release/10.0
/cc @jkoritzinsky
## Customer Impact
- [X] Customer reported
- [X] Found internally
Found by the Microsoft Store team when they were working on migrating
PurchaseApp from .NET Native. Before this change, user code could
receive an invalid, cleared RCW from ComWrappers, resulting in
unexpected exceptions after any XAML thread has exited.
## Regression
- [X] Yes
- [ ] No
Technically a regression from .NET Core 3.1's built-in WinRT support and
.NET Native
## Testing
[How was the fix verified? How was the issue missed previously? What
tests were added?]
Added unit tests to validate the behavior. Also, the fix has been
validated internally
## Risk
[High/Medium/Low. Justify the indication by mentioning how risks were
measured and addressed.]
Low risk as this only kicks in in WinRT XAML scenarios and is not
observable for single-threaded WinRT XAML apps.
**IMPORTANT**: If this backport is for a servicing release, please
verify that:
- For .NET 8 and .NET 9: The PR target branch is `release/X.0-staging`,
not `release/X.0`.
- For .NET 10+: The PR target branch is `release/X.0` (no `-staging`
suffix).
## Package authoring no longer needed in .NET 9
**IMPORTANT**: Starting with .NET 9, you no longer need to edit a NuGet
package's csproj to enable building and bump the version.
Keep in mind that we still need package authoring in .NET 8 and older
versions.
---------
Co-authored-by: Jeremy Koritzinsky <jekoritz@microsoft.com>
Co-authored-by: Jeremy Koritzinsky <jkoritzinsky@gmail.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
@github-actionsgithub-actionsBot locked and limited conversation to collaborators Apr 20, 2026
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

area-System.Runtime.InteropServicespartner-impactThis issue impacts a partner who needs to be kept updated

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

4 participants

@jkoritzinsky@Sergio0694@AaronRobinsonMSFT
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Clear RCW cache entries when releasing wrapper objects - #125754

Merged
jkoritzinsky merged 7 commits into
dotnet:mainfrom
jkoritzinsky:rcw-cache-clear
Mar 21, 2026
Merged

Clear RCW cache entries when releasing wrapper objects#125754
jkoritzinsky merged 7 commits into
dotnet:mainfrom
jkoritzinsky:rcw-cache-clear

Conversation

@jkoritzinsky

Copy link
Copy Markdown
Member

Remove native wrappers from the RCW cache in the tracker support global instance when releasing external objects for the Jupiter runtime. Without this change, a disconnected COM object wrapper could remain in the ComWrappers instance's cache. Then, if a new COM object is allocated at the same address (only possible because the COM objects were forcibly disconnected when ComWrappers.ReleaseObjects was called as part of the request from the Jupiter runtime), the old, disconnected COM object wrapper would be returned by ComWrappers.

Unblocks Microsoft Store migration to NativeAOT.

…al instance when releasing external objects for the Jupiter runtime
@jkoritzinskyjkoritzinsky added area-System.Runtime.InteropServices partner-impact This issue impacts a partner who needs to be kept updated labels Mar 18, 2026
@jkoritzinsky

Copy link
Copy Markdown
MemberAuthor

/backport to release/10.0

@github-actions

Copy link
Copy Markdown
Contributor

Started backporting to release/10.0 (link to workflow run)

@dotnet-policy-service

Copy link
Copy Markdown
Contributor

Tagging subscribers to this area: @dotnet/interop-contrib
See info in area-owners.md if you want to be subscribed.

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

This PR addresses a correctness issue in the reference-tracker (Jupiter) integration where RCW cache entries could outlive a forced disconnect, potentially causing ComWrappers to return a stale/disconnected wrapper if the native COM address is reused. This is particularly relevant for enabling NativeAOT scenarios that rely on ComWrappers.ReleaseObjects-driven disconnection.

Changes:

  • Track ReferenceTrackerNativeObjectWrapper instances released on thread-end and remove them from the RCW cache before calling ReleaseObjects.
  • Add an internal ComWrappers.RemoveWrappersFromCache(...) helper and a bulk-removal path in RcwCache.
  • Refactor RCW cache removal logic into a shared RemoveLocked(...) helper to avoid duplication.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.

FileDescription
src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/TrackerObjectManager.csCollects wrappers to remove during thread-end release and invokes RCW cache clearing before releasing objects.
src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/ComWrappers.csAdds an internal cache-removal API and implements bulk RCW cache removal with shared locked logic.

@jkoritzinsky

Copy link
Copy Markdown
MemberAuthor

/backport to release/10.0

@github-actions

Copy link
Copy Markdown
Contributor

Started backporting to release/10.0 (link to workflow run)

CopilotAI review requested due to automatic review settings March 19, 2026 20:59
@jkoritzinsky

Copy link
Copy Markdown
MemberAuthor

/backport to release/10.0

@github-actions

Copy link
Copy Markdown
Contributor

Started backporting to release/10.0 (link to workflow run)

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

This PR addresses a correctness issue in the COM tracker-support flow by ensuring RCW cache entries are cleared when external objects are released for the Jupiter runtime, preventing stale/disconnected wrappers from being returned if a COM object address is later reused.

Changes:

  • Remove eligible ReferenceTrackerNativeObjectWrapper instances from the global tracker-support ComWrappers RCW cache during ReleaseExternalObjectsFromCurrentThread.
  • Add ComWrappers/RcwCache APIs to remove multiple wrappers from the RCW cache in a single write-lock.
  • Add a regression test validating a new RCW is created after NotifyEndOfReferenceTrackingOnThread clears the cache.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 2 comments.

FileDescription
src/tests/Interop/COM/ComWrappers/GlobalInstance/GlobalInstance.csUpdates test harness behavior and adds a regression test for RCW cache clearing after thread-end notification.
src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/TrackerObjectManager.csCollects wrappers to remove and clears RCW cache entries during thread-end external object release.
src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/ComWrappers.csAdds bulk RCW cache removal support and refactors removal logic to share a locked helper.

Comment threadsrc/tests/Interop/COM/ComWrappers/GlobalInstance/GlobalInstance.cs Outdated
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
CopilotAI review requested due to automatic review settings March 19, 2026 23:22
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
@jkoritzinsky

Copy link
Copy Markdown
MemberAuthor

/backport to release/10.0

@github-actions

Copy link
Copy Markdown
Contributor

Started backporting to release/10.0 (link to workflow run)

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 3 out of 3 changed files in this pull request and generated 1 comment.

@jkoritzinsky

Copy link
Copy Markdown
MemberAuthor

/backport to release/10.0

@github-actions

Copy link
Copy Markdown
Contributor

Started backporting to release/10.0 (link to workflow run)

CopilotAI review requested due to automatic review settings March 20, 2026 17:47
@jkoritzinsky

Copy link
Copy Markdown
MemberAuthor

/backport to release/10.0

@github-actions

Copy link
Copy Markdown
Contributor

Started backporting to release/10.0 (link to workflow run)

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 3 out of 3 changed files in this pull request and generated 1 comment.

@jkoritzinsky

Copy link
Copy Markdown
MemberAuthor

/ba-g timeouts unrelated

@jkoritzinsky
jkoritzinsky merged commit ea02e22 into dotnet:mainMar 21, 2026
145 of 152 checks passed
JulieLeeMSFT pushed a commit that referenced this pull request Mar 23, 2026
…#125755)
Backport of #125754 to release/10.0
/cc @jkoritzinsky
## Customer Impact
- [X] Customer reported
- [X] Found internally
Found by the Microsoft Store team when they were working on migrating
PurchaseApp from .NET Native. Before this change, user code could
receive an invalid, cleared RCW from ComWrappers, resulting in
unexpected exceptions after any XAML thread has exited.
## Regression
- [X] Yes
- [ ] No
Technically a regression from .NET Core 3.1's built-in WinRT support and
.NET Native
## Testing
[How was the fix verified? How was the issue missed previously? What
tests were added?]
Added unit tests to validate the behavior. Also, the fix has been
validated internally
## Risk
[High/Medium/Low. Justify the indication by mentioning how risks were
measured and addressed.]
Low risk as this only kicks in in WinRT XAML scenarios and is not
observable for single-threaded WinRT XAML apps.
**IMPORTANT**: If this backport is for a servicing release, please
verify that:
- For .NET 8 and .NET 9: The PR target branch is `release/X.0-staging`,
not `release/X.0`.
- For .NET 10+: The PR target branch is `release/X.0` (no `-staging`
suffix).
## Package authoring no longer needed in .NET 9
**IMPORTANT**: Starting with .NET 9, you no longer need to edit a NuGet
package's csproj to enable building and bump the version.
Keep in mind that we still need package authoring in .NET 8 and older
versions.
---------
Co-authored-by: Jeremy Koritzinsky <jekoritz@microsoft.com>
Co-authored-by: Jeremy Koritzinsky <jkoritzinsky@gmail.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
@github-actionsgithub-actionsBot locked and limited conversation to collaborators Apr 20, 2026
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

area-System.Runtime.InteropServicespartner-impactThis issue impacts a partner who needs to be kept updated

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

4 participants

@jkoritzinsky@Sergio0694@AaronRobinsonMSFT
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

Clear RCW cache entries when releasing wrapper objects - #125754

Merged
jkoritzinsky merged 7 commits into
dotnet:mainfrom
jkoritzinsky:rcw-cache-clear
Mar 21, 2026
Merged

Clear RCW cache entries when releasing wrapper objects#125754
jkoritzinsky merged 7 commits into
dotnet:mainfrom
jkoritzinsky:rcw-cache-clear

Conversation

@jkoritzinsky

Copy link
Copy Markdown
Member

Remove native wrappers from the RCW cache in the tracker support global instance when releasing external objects for the Jupiter runtime. Without this change, a disconnected COM object wrapper could remain in the ComWrappers instance's cache. Then, if a new COM object is allocated at the same address (only possible because the COM objects were forcibly disconnected when ComWrappers.ReleaseObjects was called as part of the request from the Jupiter runtime), the old, disconnected COM object wrapper would be returned by ComWrappers.

Unblocks Microsoft Store migration to NativeAOT.

…al instance when releasing external objects for the Jupiter runtime
@jkoritzinskyjkoritzinsky added area-System.Runtime.InteropServices partner-impact This issue impacts a partner who needs to be kept updated labels Mar 18, 2026
@jkoritzinsky

Copy link
Copy Markdown
MemberAuthor

/backport to release/10.0

@github-actions

Copy link
Copy Markdown
Contributor

Started backporting to release/10.0 (link to workflow run)

@dotnet-policy-service

Copy link
Copy Markdown
Contributor

Tagging subscribers to this area: @dotnet/interop-contrib
See info in area-owners.md if you want to be subscribed.

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

This PR addresses a correctness issue in the reference-tracker (Jupiter) integration where RCW cache entries could outlive a forced disconnect, potentially causing ComWrappers to return a stale/disconnected wrapper if the native COM address is reused. This is particularly relevant for enabling NativeAOT scenarios that rely on ComWrappers.ReleaseObjects-driven disconnection.

Changes:

  • Track ReferenceTrackerNativeObjectWrapper instances released on thread-end and remove them from the RCW cache before calling ReleaseObjects.
  • Add an internal ComWrappers.RemoveWrappersFromCache(...) helper and a bulk-removal path in RcwCache.
  • Refactor RCW cache removal logic into a shared RemoveLocked(...) helper to avoid duplication.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.

FileDescription
src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/TrackerObjectManager.csCollects wrappers to remove during thread-end release and invokes RCW cache clearing before releasing objects.
src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/ComWrappers.csAdds an internal cache-removal API and implements bulk RCW cache removal with shared locked logic.

@jkoritzinsky

Copy link
Copy Markdown
MemberAuthor

/backport to release/10.0

@github-actions

Copy link
Copy Markdown
Contributor

Started backporting to release/10.0 (link to workflow run)

CopilotAI review requested due to automatic review settings March 19, 2026 20:59
@jkoritzinsky

Copy link
Copy Markdown
MemberAuthor

/backport to release/10.0

@github-actions

Copy link
Copy Markdown
Contributor

Started backporting to release/10.0 (link to workflow run)

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

This PR addresses a correctness issue in the COM tracker-support flow by ensuring RCW cache entries are cleared when external objects are released for the Jupiter runtime, preventing stale/disconnected wrappers from being returned if a COM object address is later reused.

Changes:

  • Remove eligible ReferenceTrackerNativeObjectWrapper instances from the global tracker-support ComWrappers RCW cache during ReleaseExternalObjectsFromCurrentThread.
  • Add ComWrappers/RcwCache APIs to remove multiple wrappers from the RCW cache in a single write-lock.
  • Add a regression test validating a new RCW is created after NotifyEndOfReferenceTrackingOnThread clears the cache.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 2 comments.

FileDescription
src/tests/Interop/COM/ComWrappers/GlobalInstance/GlobalInstance.csUpdates test harness behavior and adds a regression test for RCW cache clearing after thread-end notification.
src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/TrackerObjectManager.csCollects wrappers to remove and clears RCW cache entries during thread-end external object release.
src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/ComWrappers.csAdds bulk RCW cache removal support and refactors removal logic to share a locked helper.

Comment threadsrc/tests/Interop/COM/ComWrappers/GlobalInstance/GlobalInstance.cs Outdated
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
CopilotAI review requested due to automatic review settings March 19, 2026 23:22
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
@jkoritzinsky

Copy link
Copy Markdown
MemberAuthor

/backport to release/10.0

@github-actions

Copy link
Copy Markdown
Contributor

Started backporting to release/10.0 (link to workflow run)

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 3 out of 3 changed files in this pull request and generated 1 comment.

@jkoritzinsky

Copy link
Copy Markdown
MemberAuthor

/backport to release/10.0

@github-actions

Copy link
Copy Markdown
Contributor

Started backporting to release/10.0 (link to workflow run)

CopilotAI review requested due to automatic review settings March 20, 2026 17:47
@jkoritzinsky

Copy link
Copy Markdown
MemberAuthor

/backport to release/10.0

@github-actions

Copy link
Copy Markdown
Contributor

Started backporting to release/10.0 (link to workflow run)

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 3 out of 3 changed files in this pull request and generated 1 comment.

@jkoritzinsky

Copy link
Copy Markdown
MemberAuthor

/ba-g timeouts unrelated

@jkoritzinsky
jkoritzinsky merged commit ea02e22 into dotnet:mainMar 21, 2026
145 of 152 checks passed
JulieLeeMSFT pushed a commit that referenced this pull request Mar 23, 2026
…#125755)
Backport of #125754 to release/10.0
/cc @jkoritzinsky
## Customer Impact
- [X] Customer reported
- [X] Found internally
Found by the Microsoft Store team when they were working on migrating
PurchaseApp from .NET Native. Before this change, user code could
receive an invalid, cleared RCW from ComWrappers, resulting in
unexpected exceptions after any XAML thread has exited.
## Regression
- [X] Yes
- [ ] No
Technically a regression from .NET Core 3.1's built-in WinRT support and
.NET Native
## Testing
[How was the fix verified? How was the issue missed previously? What
tests were added?]
Added unit tests to validate the behavior. Also, the fix has been
validated internally
## Risk
[High/Medium/Low. Justify the indication by mentioning how risks were
measured and addressed.]
Low risk as this only kicks in in WinRT XAML scenarios and is not
observable for single-threaded WinRT XAML apps.
**IMPORTANT**: If this backport is for a servicing release, please
verify that:
- For .NET 8 and .NET 9: The PR target branch is `release/X.0-staging`,
not `release/X.0`.
- For .NET 10+: The PR target branch is `release/X.0` (no `-staging`
suffix).
## Package authoring no longer needed in .NET 9
**IMPORTANT**: Starting with .NET 9, you no longer need to edit a NuGet
package's csproj to enable building and bump the version.
Keep in mind that we still need package authoring in .NET 8 and older
versions.
---------
Co-authored-by: Jeremy Koritzinsky <jekoritz@microsoft.com>
Co-authored-by: Jeremy Koritzinsky <jkoritzinsky@gmail.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
@github-actionsgithub-actionsBot locked and limited conversation to collaborators Apr 20, 2026
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

area-System.Runtime.InteropServicespartner-impactThis issue impacts a partner who needs to be kept updated

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

4 participants

@jkoritzinsky@Sergio0694@AaronRobinsonMSFT
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Clear RCW cache entries when releasing wrapper objects - #125754

Merged
jkoritzinsky merged 7 commits into
dotnet:mainfrom
jkoritzinsky:rcw-cache-clear
Mar 21, 2026
Merged

Clear RCW cache entries when releasing wrapper objects#125754
jkoritzinsky merged 7 commits into
dotnet:mainfrom
jkoritzinsky:rcw-cache-clear

Conversation

@jkoritzinsky

Copy link
Copy Markdown
Member

Remove native wrappers from the RCW cache in the tracker support global instance when releasing external objects for the Jupiter runtime. Without this change, a disconnected COM object wrapper could remain in the ComWrappers instance's cache. Then, if a new COM object is allocated at the same address (only possible because the COM objects were forcibly disconnected when ComWrappers.ReleaseObjects was called as part of the request from the Jupiter runtime), the old, disconnected COM object wrapper would be returned by ComWrappers.

Unblocks Microsoft Store migration to NativeAOT.

…al instance when releasing external objects for the Jupiter runtime
@jkoritzinskyjkoritzinsky added area-System.Runtime.InteropServices partner-impact This issue impacts a partner who needs to be kept updated labels Mar 18, 2026
@jkoritzinsky

Copy link
Copy Markdown
MemberAuthor

/backport to release/10.0

@github-actions

Copy link
Copy Markdown
Contributor

Started backporting to release/10.0 (link to workflow run)

@dotnet-policy-service

Copy link
Copy Markdown
Contributor

Tagging subscribers to this area: @dotnet/interop-contrib
See info in area-owners.md if you want to be subscribed.

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

This PR addresses a correctness issue in the reference-tracker (Jupiter) integration where RCW cache entries could outlive a forced disconnect, potentially causing ComWrappers to return a stale/disconnected wrapper if the native COM address is reused. This is particularly relevant for enabling NativeAOT scenarios that rely on ComWrappers.ReleaseObjects-driven disconnection.

Changes:

  • Track ReferenceTrackerNativeObjectWrapper instances released on thread-end and remove them from the RCW cache before calling ReleaseObjects.
  • Add an internal ComWrappers.RemoveWrappersFromCache(...) helper and a bulk-removal path in RcwCache.
  • Refactor RCW cache removal logic into a shared RemoveLocked(...) helper to avoid duplication.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.

FileDescription
src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/TrackerObjectManager.csCollects wrappers to remove during thread-end release and invokes RCW cache clearing before releasing objects.
src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/ComWrappers.csAdds an internal cache-removal API and implements bulk RCW cache removal with shared locked logic.

@jkoritzinsky

Copy link
Copy Markdown
MemberAuthor

/backport to release/10.0

@github-actions

Copy link
Copy Markdown
Contributor

Started backporting to release/10.0 (link to workflow run)

CopilotAI review requested due to automatic review settings March 19, 2026 20:59
@jkoritzinsky

Copy link
Copy Markdown
MemberAuthor

/backport to release/10.0

@github-actions

Copy link
Copy Markdown
Contributor

Started backporting to release/10.0 (link to workflow run)

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

This PR addresses a correctness issue in the COM tracker-support flow by ensuring RCW cache entries are cleared when external objects are released for the Jupiter runtime, preventing stale/disconnected wrappers from being returned if a COM object address is later reused.

Changes:

  • Remove eligible ReferenceTrackerNativeObjectWrapper instances from the global tracker-support ComWrappers RCW cache during ReleaseExternalObjectsFromCurrentThread.
  • Add ComWrappers/RcwCache APIs to remove multiple wrappers from the RCW cache in a single write-lock.
  • Add a regression test validating a new RCW is created after NotifyEndOfReferenceTrackingOnThread clears the cache.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 2 comments.

FileDescription
src/tests/Interop/COM/ComWrappers/GlobalInstance/GlobalInstance.csUpdates test harness behavior and adds a regression test for RCW cache clearing after thread-end notification.
src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/TrackerObjectManager.csCollects wrappers to remove and clears RCW cache entries during thread-end external object release.
src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/ComWrappers.csAdds bulk RCW cache removal support and refactors removal logic to share a locked helper.

Comment threadsrc/tests/Interop/COM/ComWrappers/GlobalInstance/GlobalInstance.cs Outdated
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
CopilotAI review requested due to automatic review settings March 19, 2026 23:22
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
@jkoritzinsky

Copy link
Copy Markdown
MemberAuthor

/backport to release/10.0

@github-actions

Copy link
Copy Markdown
Contributor

Started backporting to release/10.0 (link to workflow run)

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 3 out of 3 changed files in this pull request and generated 1 comment.

@jkoritzinsky

Copy link
Copy Markdown
MemberAuthor

/backport to release/10.0

@github-actions

Copy link
Copy Markdown
Contributor

Started backporting to release/10.0 (link to workflow run)

CopilotAI review requested due to automatic review settings March 20, 2026 17:47
@jkoritzinsky

Copy link
Copy Markdown
MemberAuthor

/backport to release/10.0

@github-actions

Copy link
Copy Markdown
Contributor

Started backporting to release/10.0 (link to workflow run)

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 3 out of 3 changed files in this pull request and generated 1 comment.

@jkoritzinsky

Copy link
Copy Markdown
MemberAuthor

/ba-g timeouts unrelated

@jkoritzinsky
jkoritzinsky merged commit ea02e22 into dotnet:mainMar 21, 2026
145 of 152 checks passed
JulieLeeMSFT pushed a commit that referenced this pull request Mar 23, 2026
…#125755)
Backport of #125754 to release/10.0
/cc @jkoritzinsky
## Customer Impact
- [X] Customer reported
- [X] Found internally
Found by the Microsoft Store team when they were working on migrating
PurchaseApp from .NET Native. Before this change, user code could
receive an invalid, cleared RCW from ComWrappers, resulting in
unexpected exceptions after any XAML thread has exited.
## Regression
- [X] Yes
- [ ] No
Technically a regression from .NET Core 3.1's built-in WinRT support and
.NET Native
## Testing
[How was the fix verified? How was the issue missed previously? What
tests were added?]
Added unit tests to validate the behavior. Also, the fix has been
validated internally
## Risk
[High/Medium/Low. Justify the indication by mentioning how risks were
measured and addressed.]
Low risk as this only kicks in in WinRT XAML scenarios and is not
observable for single-threaded WinRT XAML apps.
**IMPORTANT**: If this backport is for a servicing release, please
verify that:
- For .NET 8 and .NET 9: The PR target branch is `release/X.0-staging`,
not `release/X.0`.
- For .NET 10+: The PR target branch is `release/X.0` (no `-staging`
suffix).
## Package authoring no longer needed in .NET 9
**IMPORTANT**: Starting with .NET 9, you no longer need to edit a NuGet
package's csproj to enable building and bump the version.
Keep in mind that we still need package authoring in .NET 8 and older
versions.
---------
Co-authored-by: Jeremy Koritzinsky <jekoritz@microsoft.com>
Co-authored-by: Jeremy Koritzinsky <jkoritzinsky@gmail.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
@github-actionsgithub-actionsBot locked and limited conversation to collaborators Apr 20, 2026
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

area-System.Runtime.InteropServicespartner-impactThis issue impacts a partner who needs to be kept updated

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

4 participants

@jkoritzinsky@Sergio0694@AaronRobinsonMSFT
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Clear RCW cache entries when releasing wrapper objects - #125754

Merged
jkoritzinsky merged 7 commits into
dotnet:mainfrom
jkoritzinsky:rcw-cache-clear
Mar 21, 2026
Merged

Clear RCW cache entries when releasing wrapper objects#125754
jkoritzinsky merged 7 commits into
dotnet:mainfrom
jkoritzinsky:rcw-cache-clear

Conversation

@jkoritzinsky

Copy link
Copy Markdown
Member

Remove native wrappers from the RCW cache in the tracker support global instance when releasing external objects for the Jupiter runtime. Without this change, a disconnected COM object wrapper could remain in the ComWrappers instance's cache. Then, if a new COM object is allocated at the same address (only possible because the COM objects were forcibly disconnected when ComWrappers.ReleaseObjects was called as part of the request from the Jupiter runtime), the old, disconnected COM object wrapper would be returned by ComWrappers.

Unblocks Microsoft Store migration to NativeAOT.

…al instance when releasing external objects for the Jupiter runtime
@jkoritzinskyjkoritzinsky added area-System.Runtime.InteropServices partner-impact This issue impacts a partner who needs to be kept updated labels Mar 18, 2026
@jkoritzinsky

Copy link
Copy Markdown
MemberAuthor

/backport to release/10.0

@github-actions

Copy link
Copy Markdown
Contributor

Started backporting to release/10.0 (link to workflow run)

@dotnet-policy-service

Copy link
Copy Markdown
Contributor

Tagging subscribers to this area: @dotnet/interop-contrib
See info in area-owners.md if you want to be subscribed.

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

This PR addresses a correctness issue in the reference-tracker (Jupiter) integration where RCW cache entries could outlive a forced disconnect, potentially causing ComWrappers to return a stale/disconnected wrapper if the native COM address is reused. This is particularly relevant for enabling NativeAOT scenarios that rely on ComWrappers.ReleaseObjects-driven disconnection.

Changes:

  • Track ReferenceTrackerNativeObjectWrapper instances released on thread-end and remove them from the RCW cache before calling ReleaseObjects.
  • Add an internal ComWrappers.RemoveWrappersFromCache(...) helper and a bulk-removal path in RcwCache.
  • Refactor RCW cache removal logic into a shared RemoveLocked(...) helper to avoid duplication.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.

FileDescription
src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/TrackerObjectManager.csCollects wrappers to remove during thread-end release and invokes RCW cache clearing before releasing objects.
src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/ComWrappers.csAdds an internal cache-removal API and implements bulk RCW cache removal with shared locked logic.

@jkoritzinsky

Copy link
Copy Markdown
MemberAuthor

/backport to release/10.0

@github-actions

Copy link
Copy Markdown
Contributor

Started backporting to release/10.0 (link to workflow run)

CopilotAI review requested due to automatic review settings March 19, 2026 20:59
@jkoritzinsky

Copy link
Copy Markdown
MemberAuthor

/backport to release/10.0

@github-actions

Copy link
Copy Markdown
Contributor

Started backporting to release/10.0 (link to workflow run)

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

This PR addresses a correctness issue in the COM tracker-support flow by ensuring RCW cache entries are cleared when external objects are released for the Jupiter runtime, preventing stale/disconnected wrappers from being returned if a COM object address is later reused.

Changes:

  • Remove eligible ReferenceTrackerNativeObjectWrapper instances from the global tracker-support ComWrappers RCW cache during ReleaseExternalObjectsFromCurrentThread.
  • Add ComWrappers/RcwCache APIs to remove multiple wrappers from the RCW cache in a single write-lock.
  • Add a regression test validating a new RCW is created after NotifyEndOfReferenceTrackingOnThread clears the cache.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 2 comments.

FileDescription
src/tests/Interop/COM/ComWrappers/GlobalInstance/GlobalInstance.csUpdates test harness behavior and adds a regression test for RCW cache clearing after thread-end notification.
src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/TrackerObjectManager.csCollects wrappers to remove and clears RCW cache entries during thread-end external object release.
src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/ComWrappers.csAdds bulk RCW cache removal support and refactors removal logic to share a locked helper.

Comment threadsrc/tests/Interop/COM/ComWrappers/GlobalInstance/GlobalInstance.cs Outdated
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
CopilotAI review requested due to automatic review settings March 19, 2026 23:22
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
@jkoritzinsky

Copy link
Copy Markdown
MemberAuthor

/backport to release/10.0

@github-actions

Copy link
Copy Markdown
Contributor

Started backporting to release/10.0 (link to workflow run)

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 3 out of 3 changed files in this pull request and generated 1 comment.

@jkoritzinsky

Copy link
Copy Markdown
MemberAuthor

/backport to release/10.0

@github-actions

Copy link
Copy Markdown
Contributor

Started backporting to release/10.0 (link to workflow run)

CopilotAI review requested due to automatic review settings March 20, 2026 17:47
@jkoritzinsky

Copy link
Copy Markdown
MemberAuthor

/backport to release/10.0

@github-actions

Copy link
Copy Markdown
Contributor

Started backporting to release/10.0 (link to workflow run)

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 3 out of 3 changed files in this pull request and generated 1 comment.

@jkoritzinsky

Copy link
Copy Markdown
MemberAuthor

/ba-g timeouts unrelated

@jkoritzinsky
jkoritzinsky merged commit ea02e22 into dotnet:mainMar 21, 2026
145 of 152 checks passed
JulieLeeMSFT pushed a commit that referenced this pull request Mar 23, 2026
…#125755)
Backport of #125754 to release/10.0
/cc @jkoritzinsky
## Customer Impact
- [X] Customer reported
- [X] Found internally
Found by the Microsoft Store team when they were working on migrating
PurchaseApp from .NET Native. Before this change, user code could
receive an invalid, cleared RCW from ComWrappers, resulting in
unexpected exceptions after any XAML thread has exited.
## Regression
- [X] Yes
- [ ] No
Technically a regression from .NET Core 3.1's built-in WinRT support and
.NET Native
## Testing
[How was the fix verified? How was the issue missed previously? What
tests were added?]
Added unit tests to validate the behavior. Also, the fix has been
validated internally
## Risk
[High/Medium/Low. Justify the indication by mentioning how risks were
measured and addressed.]
Low risk as this only kicks in in WinRT XAML scenarios and is not
observable for single-threaded WinRT XAML apps.
**IMPORTANT**: If this backport is for a servicing release, please
verify that:
- For .NET 8 and .NET 9: The PR target branch is `release/X.0-staging`,
not `release/X.0`.
- For .NET 10+: The PR target branch is `release/X.0` (no `-staging`
suffix).
## Package authoring no longer needed in .NET 9
**IMPORTANT**: Starting with .NET 9, you no longer need to edit a NuGet
package's csproj to enable building and bump the version.
Keep in mind that we still need package authoring in .NET 8 and older
versions.
---------
Co-authored-by: Jeremy Koritzinsky <jekoritz@microsoft.com>
Co-authored-by: Jeremy Koritzinsky <jkoritzinsky@gmail.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
@github-actionsgithub-actionsBot locked and limited conversation to collaborators Apr 20, 2026
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

area-System.Runtime.InteropServicespartner-impactThis issue impacts a partner who needs to be kept updated

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

4 participants

@jkoritzinsky@Sergio0694@AaronRobinsonMSFT
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

Clear RCW cache entries when releasing wrapper objects - #125754

Merged
jkoritzinsky merged 7 commits into
dotnet:mainfrom
jkoritzinsky:rcw-cache-clear
Mar 21, 2026
Merged

Clear RCW cache entries when releasing wrapper objects#125754
jkoritzinsky merged 7 commits into
dotnet:mainfrom
jkoritzinsky:rcw-cache-clear

Conversation

@jkoritzinsky

Copy link
Copy Markdown
Member

Remove native wrappers from the RCW cache in the tracker support global instance when releasing external objects for the Jupiter runtime. Without this change, a disconnected COM object wrapper could remain in the ComWrappers instance's cache. Then, if a new COM object is allocated at the same address (only possible because the COM objects were forcibly disconnected when ComWrappers.ReleaseObjects was called as part of the request from the Jupiter runtime), the old, disconnected COM object wrapper would be returned by ComWrappers.

Unblocks Microsoft Store migration to NativeAOT.

…al instance when releasing external objects for the Jupiter runtime
@jkoritzinskyjkoritzinsky added area-System.Runtime.InteropServices partner-impact This issue impacts a partner who needs to be kept updated labels Mar 18, 2026
@jkoritzinsky

Copy link
Copy Markdown
MemberAuthor

/backport to release/10.0

@github-actions

Copy link
Copy Markdown
Contributor

Started backporting to release/10.0 (link to workflow run)

@dotnet-policy-service

Copy link
Copy Markdown
Contributor

Tagging subscribers to this area: @dotnet/interop-contrib
See info in area-owners.md if you want to be subscribed.

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

This PR addresses a correctness issue in the reference-tracker (Jupiter) integration where RCW cache entries could outlive a forced disconnect, potentially causing ComWrappers to return a stale/disconnected wrapper if the native COM address is reused. This is particularly relevant for enabling NativeAOT scenarios that rely on ComWrappers.ReleaseObjects-driven disconnection.

Changes:

  • Track ReferenceTrackerNativeObjectWrapper instances released on thread-end and remove them from the RCW cache before calling ReleaseObjects.
  • Add an internal ComWrappers.RemoveWrappersFromCache(...) helper and a bulk-removal path in RcwCache.
  • Refactor RCW cache removal logic into a shared RemoveLocked(...) helper to avoid duplication.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.

FileDescription
src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/TrackerObjectManager.csCollects wrappers to remove during thread-end release and invokes RCW cache clearing before releasing objects.
src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/ComWrappers.csAdds an internal cache-removal API and implements bulk RCW cache removal with shared locked logic.

@jkoritzinsky

Copy link
Copy Markdown
MemberAuthor

/backport to release/10.0

@github-actions

Copy link
Copy Markdown
Contributor

Started backporting to release/10.0 (link to workflow run)

CopilotAI review requested due to automatic review settings March 19, 2026 20:59
@jkoritzinsky

Copy link
Copy Markdown
MemberAuthor

/backport to release/10.0

@github-actions

Copy link
Copy Markdown
Contributor

Started backporting to release/10.0 (link to workflow run)

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

This PR addresses a correctness issue in the COM tracker-support flow by ensuring RCW cache entries are cleared when external objects are released for the Jupiter runtime, preventing stale/disconnected wrappers from being returned if a COM object address is later reused.

Changes:

  • Remove eligible ReferenceTrackerNativeObjectWrapper instances from the global tracker-support ComWrappers RCW cache during ReleaseExternalObjectsFromCurrentThread.
  • Add ComWrappers/RcwCache APIs to remove multiple wrappers from the RCW cache in a single write-lock.
  • Add a regression test validating a new RCW is created after NotifyEndOfReferenceTrackingOnThread clears the cache.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 2 comments.

FileDescription
src/tests/Interop/COM/ComWrappers/GlobalInstance/GlobalInstance.csUpdates test harness behavior and adds a regression test for RCW cache clearing after thread-end notification.
src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/TrackerObjectManager.csCollects wrappers to remove and clears RCW cache entries during thread-end external object release.
src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/ComWrappers.csAdds bulk RCW cache removal support and refactors removal logic to share a locked helper.

Comment threadsrc/tests/Interop/COM/ComWrappers/GlobalInstance/GlobalInstance.cs Outdated
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
CopilotAI review requested due to automatic review settings March 19, 2026 23:22
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
@jkoritzinsky

Copy link
Copy Markdown
MemberAuthor

/backport to release/10.0

@github-actions

Copy link
Copy Markdown
Contributor

Started backporting to release/10.0 (link to workflow run)

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 3 out of 3 changed files in this pull request and generated 1 comment.

@jkoritzinsky

Copy link
Copy Markdown
MemberAuthor

/backport to release/10.0

@github-actions

Copy link
Copy Markdown
Contributor

Started backporting to release/10.0 (link to workflow run)

CopilotAI review requested due to automatic review settings March 20, 2026 17:47
@jkoritzinsky

Copy link
Copy Markdown
MemberAuthor

/backport to release/10.0

@github-actions

Copy link
Copy Markdown
Contributor

Started backporting to release/10.0 (link to workflow run)

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 3 out of 3 changed files in this pull request and generated 1 comment.

@jkoritzinsky

Copy link
Copy Markdown
MemberAuthor

/ba-g timeouts unrelated

@jkoritzinsky
jkoritzinsky merged commit ea02e22 into dotnet:mainMar 21, 2026
145 of 152 checks passed
JulieLeeMSFT pushed a commit that referenced this pull request Mar 23, 2026
…#125755)
Backport of #125754 to release/10.0
/cc @jkoritzinsky
## Customer Impact
- [X] Customer reported
- [X] Found internally
Found by the Microsoft Store team when they were working on migrating
PurchaseApp from .NET Native. Before this change, user code could
receive an invalid, cleared RCW from ComWrappers, resulting in
unexpected exceptions after any XAML thread has exited.
## Regression
- [X] Yes
- [ ] No
Technically a regression from .NET Core 3.1's built-in WinRT support and
.NET Native
## Testing
[How was the fix verified? How was the issue missed previously? What
tests were added?]
Added unit tests to validate the behavior. Also, the fix has been
validated internally
## Risk
[High/Medium/Low. Justify the indication by mentioning how risks were
measured and addressed.]
Low risk as this only kicks in in WinRT XAML scenarios and is not
observable for single-threaded WinRT XAML apps.
**IMPORTANT**: If this backport is for a servicing release, please
verify that:
- For .NET 8 and .NET 9: The PR target branch is `release/X.0-staging`,
not `release/X.0`.
- For .NET 10+: The PR target branch is `release/X.0` (no `-staging`
suffix).
## Package authoring no longer needed in .NET 9
**IMPORTANT**: Starting with .NET 9, you no longer need to edit a NuGet
package's csproj to enable building and bump the version.
Keep in mind that we still need package authoring in .NET 8 and older
versions.
---------
Co-authored-by: Jeremy Koritzinsky <jekoritz@microsoft.com>
Co-authored-by: Jeremy Koritzinsky <jkoritzinsky@gmail.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
@github-actionsgithub-actionsBot locked and limited conversation to collaborators Apr 20, 2026
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

area-System.Runtime.InteropServicespartner-impactThis issue impacts a partner who needs to be kept updated

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

4 participants

@jkoritzinsky@Sergio0694@AaronRobinsonMSFT