Clear RCW cache entries when releasing wrapper objects#125754
Clear RCW cache entries when releasing wrapper objects#125754jkoritzinsky wants to merge 5 commits intodotnet:mainfrom
Conversation
…al instance when releasing external objects for the Jupiter runtime
|
/backport to release/10.0 |
|
Started backporting to |
|
Tagging subscribers to this area: @dotnet/interop-contrib |
There was a problem hiding this comment.
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
ReferenceTrackerNativeObjectWrapperinstances released on thread-end and remove them from the RCW cache before callingReleaseObjects. - Add an internal
ComWrappers.RemoveWrappersFromCache(...)helper and a bulk-removal path inRcwCache. - 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.
| File | Description |
|---|---|
src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/TrackerObjectManager.cs |
Collects 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.cs |
Adds an internal cache-removal API and implements bulk RCW cache removal with shared locked logic. |
src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/TrackerObjectManager.cs
Outdated
Show resolved
Hide resolved
src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/TrackerObjectManager.cs
Outdated
Show resolved
Hide resolved
src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/ComWrappers.cs
Outdated
Show resolved
Hide resolved
src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/TrackerObjectManager.cs
Outdated
Show resolved
Hide resolved
src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/TrackerObjectManager.cs
Outdated
Show resolved
Hide resolved
|
/backport to release/10.0 |
|
Started backporting to |
|
/backport to release/10.0 |
|
Started backporting to |
There was a problem hiding this comment.
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
ReferenceTrackerNativeObjectWrapperinstances from the global tracker-supportComWrappersRCW cache duringReleaseExternalObjectsFromCurrentThread. - Add
ComWrappers/RcwCacheAPIs to remove multiple wrappers from the RCW cache in a single write-lock. - Add a regression test validating a new RCW is created after
NotifyEndOfReferenceTrackingOnThreadclears the cache.
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
| src/tests/Interop/COM/ComWrappers/GlobalInstance/GlobalInstance.cs | Updates 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.cs | Collects wrappers to remove and clears RCW cache entries during thread-end external object release. |
| src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/ComWrappers.cs | Adds bulk RCW cache removal support and refactors removal logic to share a locked helper. |
src/tests/Interop/COM/ComWrappers/GlobalInstance/GlobalInstance.cs
Outdated
Show resolved
Hide resolved
src/libraries/System.Private.CoreLib/src/System/Runtime/InteropServices/TrackerObjectManager.cs
Outdated
Show resolved
Hide resolved
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
|
/backport to release/10.0 |
|
Started backporting to |
| nativeObjectWrapper.DisconnectTracker(); | ||
|
|
||
| if (nativeObjectWrapper.ComWrappers == GlobalInstanceForTrackerSupport) | ||
| { | ||
| wrappersToRemove.Add(nativeObjectWrapper); |
There was a problem hiding this comment.
ReleaseExternalObjectsFromCurrentThread calls DisconnectTracker() for all ReferenceTrackerNativeObjectWrapper instances in the current context, regardless of owning ComWrappers, but only removes wrappers from the RCW cache when nativeObjectWrapper.ComWrappers == GlobalInstanceForTrackerSupport. This leaves disconnected wrappers in other ComWrappers instances' RCW caches, so those instances can still return a stale/disconnected wrapper for the same COM address later. Consider removing from each wrapper's owning ComWrappers cache (eg group wrappers by nativeObjectWrapper.ComWrappers and call RemoveWrappersFromCache per instance), or alternatively limit the disconnect/release flow to only wrappers owned by the global tracker-support instance.
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.ReleaseObjectswas called as part of the request from the Jupiter runtime), the old, disconnected COM object wrapper would be returned byComWrappers.Unblocks Microsoft Store migration to NativeAOT.