Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[mono] Possible GC hole in runtime invoke #58957

Closed
lambdageek opened this issue Sep 10, 2021 · 6 comments · Fixed by #58978
Closed

[mono] Possible GC hole in runtime invoke #58957

lambdageek opened this issue Sep 10, 2021 · 6 comments · Fixed by #58978
Assignees
Milestone

Comments

@lambdageek
Copy link
Member

Introduced by #58215 and the 6.0 backport #58364

The issue was: if a method is returning a large valuetype that will need to be boxed into a MonoObject that is bigger than the fixed-size stack allocated buffer that we prepare, use malloc to allocate a bigger buffer on the unmanaged heap and store the result there and then copy it over into a MonoObject.

The problem is that while the value is only in the unmanaged heap buffer, if it has any reference types pointing into the managed heap, those pointers are not visible to the GC. So if there's a collection between when the invoked method returns and the point where we copy the result to the MonoObject, we will have GC holes.


Probably what we need to do is use alloca (upto some bigger bound - originally it was 256 bytes, but maybe it needs to be larger).

Alternately, if we always expect to box the result anyway, we could just write it directly into the MonoObject (I think the managed code would always have write barriers there).

@dotnet-issue-labeler
Copy link

I couldn't figure out the best area label to add to this issue. If you have write-permissions please help me learn by adding exactly one area label.

@dotnet-issue-labeler dotnet-issue-labeler bot added the untriaged New issue has not been triaged by the area owner label Sep 10, 2021
@ghost
Copy link

ghost commented Sep 10, 2021

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

Issue Details

Introduced by #58215 and the 6.0 backport #58364

The issue was: if a method is returning a large valuetype that will need to be boxed into a MonoObject that is bigger than the fixed-size stack allocated buffer that we prepare, use malloc to allocate a bigger buffer on the unmanaged heap and store the result there and then copy it over into a MonoObject.

The problem is that while the value is only in the unmanaged heap buffer, if it has any reference types pointing into the managed heap, those pointers are not visible to the GC. So if there's a collection between when the invoked method returns and the point where we copy the result to the MonoObject, we will have GC holes.


Probably what we need to do is use alloca (upto some bigger bound - originally it was 256 bytes, but maybe it needs to be larger).

Alternately, if we always expect to box the result anyway, we could just write it directly into the MonoObject (I think the managed code would always have write barriers there).

Author: lambdageek
Assignees: -
Labels:

untriaged, area-GC-mono

Milestone: -

@lambdageek lambdageek added this to the 6.0.0 milestone Sep 10, 2021
@lambdageek
Copy link
Member Author

@marek-safar FYI - I think we should probably revert #58364 from 6.0, but also we shoudl throw an ExecutionEngineException if the valuetype is too big (just reverting will mean we're going to go back to a buffer overflow). That will break a System.Text.Json test that was doing something with a large valuetype.

@lambdageek lambdageek self-assigned this Sep 10, 2021
@lambdageek lambdageek removed the untriaged New issue has not been triaged by the area owner label Sep 10, 2021
@BrzVlad
Copy link
Member

BrzVlad commented Sep 10, 2021

I think we should just use alloca without thinking about it. There is no added risk here.

@lambdageek
Copy link
Member Author

I think we should just use alloca without thinking about it. There is no added risk here.

if the alloca causes a stack overflow in unmanaged code, are we going to get a managed stack overflow exception on the thread? or will it be some native crash?

@BrzVlad
Copy link
Member

BrzVlad commented Sep 10, 2021

On some platforms we have stack guard but surely not on all of them. Anyhow, I don't see why it would matter. Any code can potentially stack overflow and we are not causing unreasonable stack increase here. Whatever the size of the valuetype, instances of it would likely still be stored plenty of times on stack frames from managed code. And it's not like the code before wouldn't also stack overflow. The same stack space would still be written when initializing the valuetype, only that now it overflows into other frames making everything even worse.

lambdageek added a commit to lambdageek/runtime that referenced this issue Sep 11, 2021
@ghost ghost added the in-pr There is an active PR which will close this issue when it is merged label Sep 11, 2021
github-actions bot pushed a commit that referenced this issue Sep 12, 2021
Fixes #58957
Related to #58215 which was attempting to
fix #58190
lambdageek added a commit that referenced this issue Sep 12, 2021
* [mini] Use alloca for runtime_invoke retval buffer

Fixes #58957
Related to #58215 which was attempting to
fix #58190

* Set initial return buffer size to TARGET_SIZEOF_VOID_P

In the common case we use the return buffer just to hold a pointer to
the return value
Anipik pushed a commit that referenced this issue Sep 13, 2021
)

* [mini] Use alloca for runtime_invoke retval buffer

Fixes #58957
Related to #58215 which was attempting to
fix #58190

* Set initial return buffer size to TARGET_SIZEOF_VOID_P

In the common case we use the return buffer just to hold a pointer to
the return value

Co-authored-by: Aleksey Kliger <alklig@microsoft.com>
Co-authored-by: Aleksey Kliger <aleksey@lambdageek.org>
@ghost ghost removed the in-pr There is an active PR which will close this issue when it is merged label Sep 13, 2021
@ghost ghost locked as resolved and limited conversation to collaborators Nov 3, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants