Skip to content

Conversation

@janvorli
Copy link
Member

This change fixes an intermittent issue that was showing up in
the System.Linq.Expressions.Tests suite. When the delegate class
was in a collectible ALC, some of the stubs were being used even
after the underlying loader allocator was deleted, thus the memory
the stubs occupied was already unmapped.

Before my recent W^X change, the stubs were always being allocated
from an executable allocator / executable heap in the global loader
allocator due to a bug in the AssemblyLoaderAllocator::SetCollectible
and AssemblyLoaderAllocator::Init ordering (the SetCollectible
was being called before the Init, so the m_pStubHeap was not yet
set and the ShuffleThunkCache was being passed NULL as the heap
pointer. The cache handles that case as a request to allocate from
global executable heap.

In this fix, I've changed the AssemblyLoaderAllocator::Init to pass
the SystemDomain::GetGlobalLoaderAllocator()->GetExecutableHeap()
as the heap to the ShuffleThunkCache constructor. It is a workaround
until the actual issue with stubs outliving the delegate classes
is understood and fixed.

Besides the fix, this change also fixes two unrelated issues that
would only possibly cause trouble when the W^X is enabled. There
were two places where memory was being reserved by the new
ExecutableAllocator, but cleaned up using the ClrVirtualFree.

Close #55536

This change fixes an intermittent issue that was showing up in
the System.Linq.Expressions.Tests suite. When the delegate class
was in a collectible ALC, some of the stubs were being used even
after the underlying loader allocator was deleted, thus the memory
the stubs occupied was already unmapped.

Before my recent W^X change, the stubs were always being allocated
from an executable allocator / executable heap in the global loader
allocator due to a bug in the AssemblyLoaderAllocator::SetCollectible
and AssemblyLoaderAllocator::Init ordering (the SetCollectible
was being called before the Init, so the m_pStubHeap was not yet
set and the ShuffleThunkCache was being passed NULL as the heap
pointer. The cache handles that case as a request to allocate from
global executable heap.

In this fix, I've changed the AssemblyLoaderAllocator::Init to pass
the SystemDomain::GetGlobalLoaderAllocator()->GetExecutableHeap()
as the heap to the ShuffleThunkCache constructor. It is a workaround
until the actual issue with stubs outliving the delegate classes
is understood and fixed.

Besides the fix, this change also fixes two unrelated issues that
would only possibly cause trouble when the W^X is enabled. There
were two places where memory was being reserved by the new
ExecutableAllocator, but cleaned up using the ClrVirtualFree.
@janvorli janvorli added this to the 6.0.0 milestone Jul 15, 2021
@janvorli janvorli requested a review from jkotas July 15, 2021 07:21
@janvorli janvorli self-assigned this Jul 15, 2021
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.

Thank you!

@stephentoub
Copy link
Member

Thank you for tracking it down.

@janvorli janvorli closed this Jul 15, 2021
@janvorli janvorli reopened this Jul 15, 2021
@janvorli
Copy link
Member Author

The CI is acting weirdly. I cannot restart the failed leg and even closing / reopening the PR doesn't have any effect.

@janvorli
Copy link
Member Author

Ah, it seems like the CI is just overloaded. Now it started to rerun the legs after an hour of inactivity.

@janvorli janvorli merged commit 82c75a9 into dotnet:main Jul 15, 2021
@janvorli janvorli deleted the fix-stub-crash branch July 15, 2021 17:46
@ghost ghost locked as resolved and limited conversation to collaborators Aug 14, 2021
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.

Non-deterministic but frequent crashes from System.Linq.Expressions.Tests

3 participants