[cominterop] Add coop handle enter/return on native CCW methods #21365
Merged
lambdageek merged 2 commits intomono:mainfrom Dec 13, 2021
Merged
[cominterop] Add coop handle enter/return on native CCW methods #21365lambdageek merged 2 commits intomono:mainfrom
lambdageek merged 2 commits intomono:mainfrom
Conversation
The CCW methods for IUnknown (and in principle IDispatch - except they all have trivial bodies) are native C code in the runtime that may allocate coop handles. Add a coop handle frame around the entire call in order to make sure they're cleaned up and don't retain a reference. This helps fix managed object leaks with code like: ``` var o = new SomeClass(); var pUnk = Marshal.GetIUnknownForObject(o); int c = Marshal.Release(pUnk); o = null; ``` Which retains a reference to the `SomeClass` instance that won't be collected until the thread dies, despite cleaning up the IUnknown refcount. The underling ccw addref/release methods leak coop handles on the thread. This is not an issue when the CCW calls some managed method because there are no coop handles there until some icall (at which point it will set up the coop handle stack properly).
acc120d to
8de1b6f
Compare
Member
Author
|
/backport to 2020-02 |
Contributor
|
Started backporting to 2020-02: https://github.com/mono/mono/actions/runs/1565238389 |
Member
Author
|
@monojenkins build failed |
thaystg
approved these changes
Dec 13, 2021
naricc
approved these changes
Dec 13, 2021
lateralusX
added a commit
to lateralusX/runtime
that referenced
this pull request
Mar 23, 2022
ThomasKuehne
pushed a commit
to ThomasKuehne/mono
that referenced
this pull request
Mar 23, 2024
…#21365) * [tests] Add CCW GetIUnknownForObject leak test * [cominterop] Add coop handle enter/return on native CCW methods The CCW methods for IUnknown (and in principle IDispatch - except they all have trivial bodies) are native C code in the runtime that may allocate coop handles. Add a coop handle frame around the entire call in order to make sure they're cleaned up and don't retain a reference. This helps fix managed object leaks with code like: ``` var o = new SomeClass(); var pUnk = Marshal.GetIUnknownForObject(o); int c = Marshal.Release(pUnk); o = null; ``` Which retains a reference to the `SomeClass` instance that won't be collected until the thread dies, despite cleaning up the IUnknown refcount. The underling ccw addref/release methods leak coop handles on the thread. This is not an issue when the CCW calls some managed method because there are no coop handles there until some icall (at which point it will set up the coop handle stack properly).
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The CCW methods for IUnknown (and in principle IDispatch - except they all have trivial bodies) are native C code in the runtime that may allocate coop handles. Add a coop handle frame around the entire call in order to make sure they're cleaned up and don't retain a reference.
This helps fix managed object leaks with code like:
Which retains a reference to the
SomeClassinstance that won't be collected until the thread dies, despite cleaning up the IUnknown refcount. The underling ccw addref/release methods leak coop handles on the thread.This is not an issue when the CCW calls some managed method because there are no coop handles there until some icall (at which point it will set up the coop handle stack properly).