Fix issue with locals overlapping out of scope GCFrame (dotnet/coreclr#26763)
authorJan Vorlicek <janvorli@microsoft.com>
Mon, 23 Sep 2019 15:13:20 +0000 (17:13 +0200)
committerGitHub <noreply@github.com>
Mon, 23 Sep 2019 15:13:20 +0000 (17:13 +0200)
commit0f9a15635600ecd8fa74f718d0c8cabdd8334fb7
tree108479eb5475d85c132efbaea58bf4fbd4ca571c
parentd219a2ae8f5d0e8a8b8425bfa171604d5061a7e5
Fix issue with locals overlapping out of scope GCFrame (dotnet/coreclr#26763)

* Fix issue with locals overlapping out of scope GCFrame

More aggressive C/C++ optimizations done by VS2019 are breaking fragile
assumptions of the CoreCLR "manually managed code".

Unwinding of Frame chains accesses stack local variables after the stack
frame has been unwound, but it depends on their content to be left
intact. The new compiler is breaking this assumption by stack-packing a
different variable over it.

This change fixes the problem by adding a destructor to GCFrame that
pops the frame from the per-thread Frame list.

I also had to refactor two functions where the compiler was complaining
about mixing SEH and C++ EH in single function.

With these changes applied, there was still a problem that I've discovered
when running CoreCLR tests with GCStress 3. When the
ExceptionTracker::m_pInitialExplicitFrame was still pointing to a frame
that was already removed from the explicit Frame chain. When the
ExceptionTracker::HasFrameBeenUnwoundByAnyActiveException was walking
the frame chain starting at m_pInitialExplicitFrame to figure out if a given
frame was already unwound, it has walked to the destroyed GCFrame and
crashed.

To fix that, the chain from the initial explicit frame is updated so
that it stays valid (effectively, the destroyed GCFrame is removed from
it). It was also necessary to handle the case when the destroyed GCFrame
was the ExceptionTracker::m_pLimitFrame. The limit frame needs to be
updated to the next frame so that it can be reached on the chain from
the initial explicit frame.

* Reflect PR feedback

Change the switching to coop mode in ~GCFrame from holder based to
manual.

Commit migrated from https://github.com/dotnet/coreclr/commit/6059e75e13593b0820e178f8baaace32c09aca6e
src/coreclr/src/vm/assembly.cpp
src/coreclr/src/vm/exceptionhandling.cpp
src/coreclr/src/vm/exceptionhandling.h
src/coreclr/src/vm/frames.cpp
src/coreclr/src/vm/frames.h
src/coreclr/src/vm/syncblk.cpp