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

GC stress fix for reverse pinvoke stubs #37432

Merged

Conversation

AndyAyersMS
Copy link
Member

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.

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.
@ghost
Copy link

ghost commented Jun 4, 2020

Tagging subscribers to this area: @ViktorHofer
Notify danmosemsft if you want to be subscribed.

@AndyAyersMS
Copy link
Member Author

cc @jkotas @jkoritzinsky

More notes / logs / etc in the linked issue.

// So, suppress GC for the reverse PInvoke stubs.
if (!pThread->PreemptiveGCDisabled())
{
_ASSERTE(pMD->IsILStub());
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
_ASSERTE(pMD->IsILStub());
_ASSERTE(pMD->HasUnmanagedCallersOnlyAttribute());

The method does not have to be IL stub.

Copy link
Member

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.

Copy link
Member Author

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.

Copy link
Member

@jkotas jkotas left a comment

Choose a reason for hiding this comment

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

LGTM. Thanks!

@AndyAyersMS
Copy link
Member Author

Added some GC stress runs.

@AndyAyersMS
Copy link
Member Author

GC stress failures are known issues (#37238, #33948). So no new failures.

@AndyAyersMS AndyAyersMS merged commit 2f22b88 into dotnet:master Jun 5, 2020
@AndyAyersMS AndyAyersMS deleted the FixReversePInvokeGCStressIssue branch June 5, 2020 17:50
@ghost ghost locked as resolved and limited conversation to collaborators Dec 8, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Test failed: JIT\Performance\CodeQuality\BenchmarksGame\pidigits\pidigits-3\pidigits-3.cmd
3 participants