-
Notifications
You must be signed in to change notification settings - Fork 4.8k
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
Rework unloadability fix #68550
Rework unloadability fix #68550
Conversation
The recent fix had a problem when GC collected the managed Assembly loaded via the Load override or the Resolving event before we added the reference between the related native LoaderAllocators. The managed LoaderAllocator of the ALC we've loaded the Assembly into was collected and we couldn't create the managed Type objects for the interfaces from that assembly in the GetInterfaces call on a type that implemented those. This change fixes it by moving the creation of reference between the native LoaderAllocators to the RuntimeInvokeHostAssemblyResolver where we still have a live managed reference to the loaded Assembly.
Tagging subscribers to this area: @vitek-karas, @agocke, @VSadov Issue DetailsThis change reworks the recent fix of dependency between two collectible This change fixes the problem by moving the creation of reference between the native Close #68112
|
@@ -1153,9 +1154,10 @@ namespace BINDER_SPACE | |||
|
|||
#if !defined(DACCESS_COMPILE) | |||
HRESULT AssemblyBinderCommon::BindUsingHostAssemblyResolver(/* in */ INT_PTR pManagedAssemblyLoadContextToBindWithin, |
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.
We can probably do some cleanup around just getting the managed ALC pointer from the AssemblyBinder now that we have the binder - after this change goes in, since we want to backport this.
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.
We should also file a docs issue for how we're now explicitly blocking the non-collectible to collectible assembly: https://github.com/dotnet/docs/issues/new?template=dotnet-breaking-change.md
Or I think marking this with the 'breaking-change' label gives you all the instructions for that.
Make it test that we throw an exception when the parent ALC is not collectible.
Added When you commit this breaking change:
Tagging @dotnet/compat for awareness of the breaking change. |
This change ports two unloadability fixes for issues found by a customer. * dotnet#68550 that adds reference between native `LoaderAllocator`s of two collectible `AssemblyLoadContexts` when one of them is used to resolve assembly using the other one. This reference ensures that the one that provides the resolved `Assembly` isn't collected before the one that uses it. * dotnet#68336 that adds a missing lock around `m_LoaderAllocatorReferences` iteration during assembly load context destruction.
* [Release/6.0] Port unloadability fixes This change ports two unloadability fixes for issues found by a customer. * #68550 that adds reference between native `LoaderAllocator`s of two collectible `AssemblyLoadContexts` when one of them is used to resolve assembly using the other one. This reference ensures that the one that provides the resolved `Assembly` isn't collected before the one that uses it. * #68336 that adds a missing lock around `m_LoaderAllocatorReferences` iteration during assembly load context destruction. * Remove breaking change part The change in main has added an exception in case a collectible `Assembly` is resolved into a non-collectible `AssemblyLoadContext`. Although that is incorrect, there are cases when it would work. So the added exception is a breaking change that I think we likely don't want to get into 6.0
This change reworks the recent fix of dependency between two collectible
AssemblyLoadContext
's when one context uses the other one for resolving its assemblies. There was a problem with the previous solution that has shown up in the newly added test when running with GCStress 3 enabled.When we create the reference between the related native LoaderAllocator instances, the managed
LoaderAllocator
of theAssemblyLoadContext
that was used to resolve the assembly needs to be alive so that we can create a handle to it in the context of the parentAssemblyLoadContext
and keep it alive for the lifetime of the parentAssemblyLoadContext
.With the previous change, if the
AssemblyLoadContext
that was used to resolve the assembly was collected before theAssemblyLoadContext.Load
override or the related Resolving event returned and the managed representation of the resolved assembly was collected too, we would not be able to create managedSystem.Reflection.Type
instances for the types from the resolved assembly after that. So e.g. callingGetInterfaces
on aType
would fail or crash.This change fixes the problem by moving the creation of reference between the native
LoaderAllocator
s to theRuntimeInvokeHostAssemblyResolver
where the managedAssembly
reference is still alive and thus the related managedLoaderAllocator
must be alive too.Close #68112