-
Notifications
You must be signed in to change notification settings - Fork 4.9k
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
GC stress fix for reverse pinvoke stubs #37432
GC stress fix for reverse pinvoke stubs #37432
Conversation
Reverse PInvoke stubs change the thread to preemptive mode before they exit. Often the epilog immediately follows this helper call, but in some cases there may be a region with a few instructions before we reach the epilog. If there is a normal GC triggered while the method is in this region then the runtime will not report GC references from the stub frame. If the stub method is fully interruptible we will put GC coverage interrupts in this region when doing GC stress. When these trigger a GC then the runtime will report GC references from the stub frame. So if while executing in this region we happen to do a normal GC and then a stress invoked GC, the stress mode GC can find invalid GC references in the frame, as the objects referenced could have been collected/moved by the normal GC that happened just before. There are a couple of avenues for a fix, but since this is a stress mode only problem, I've modified GC stress avoid invoking a GC when the thread is already in preemptive mode and the method is a reverse PINvoke stub. Fixes dotnet#13720.
Tagging subscribers to this area: @ViktorHofer |
More notes / logs / etc in the linked issue. |
src/coreclr/src/vm/gccover.cpp
Outdated
// So, suppress GC for the reverse PInvoke stubs. | ||
if (!pThread->PreemptiveGCDisabled()) | ||
{ | ||
_ASSERTE(pMD->IsILStub()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
_ASSERTE(pMD->IsILStub()); | |
_ASSERTE(pMD->HasUnmanagedCallersOnlyAttribute()); |
The method does not have to be IL stub.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Scratch that. It can be any method. PInvoke stub with an inlined frame can appear in any method.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good point. That was just some extra paranoia.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM. Thanks!
Added some GC stress runs. |
Reverse PInvoke stubs change the thread to preemptive mode before
they exit. Often the epilog immediately follows this helper call,
but in some cases there may be a region with a few instructions
before we reach the epilog.
If there is a normal GC triggered while the method is in this region
then the runtime will not report GC references from the stub frame.
If the stub method is fully interruptible we will put GC coverage
interrupts in this region when doing GC stress. When these trigger a GC
then the runtime will report GC references from the stub frame.
So if while executing in this region we happen to do a normal GC and then
a stress invoked GC, the stress mode GC can find invalid GC references
in the frame, as the objects referenced could have been collected/moved
by the normal GC that happened just before.
There are a couple of avenues for a fix, but since this is a stress mode
only problem, I've modified GC stress avoid invoking a GC when the thread
is already in preemptive mode and the method is a reverse PInvoke stub.
Fixes #13720.