Skip to content

[Breaking change]: Resolving collectible assembly into a non-collectible AssemblyLoadContext now throws #29200

@janvorli

Description

@janvorli

Description

We were incorrectly allowing resolving collectible assemblies into a non-collectible AssemblyLoadContext. That may seemingly work ok in some cases and lead to runtime crashes or unexpected NullReferenceException in others.
The change in dotnet/runtime#68550 prevents that incorrect behavior by throwing an exception when the AssemblyLoadContext.Load or the AssemblyLoadContext.Resolving event returns a collectible Assembly and the AssemblyLoadContext is non-collectible.

Version

.NET 7 Preview 5

Previous behavior

Returning a collectible Assembly in the AssemblyLoadContext.Load override or the AssemblyLoadContext.Resolving event of a non-collectible AssemblyLoadContext doesn't cause any exceptions to be thrown.

New behavior

Returning a collectible Assembly in the AssemblyLoadContext.Load override or the AssemblyLoadContext.Resolving event of a non-collectible AssemblyLoadContext results in throwing a System.IO.FileLoadException with System.NotSupportedException inner exception.

Type of breaking change

  • Binary incompatible: Existing binaries may encounter a breaking change in behavior, such as failure to load/execute or different run-time behavior.
  • Source incompatible: Source code may encounter a breaking change in behavior when targeting the new runtime/component/SDK, such as compile errors or different run-time behavior.

Reason for change

This change fixes a bug. The collectible Assembly would be collected while the AssemblyLoadContext that has a reference to it is alive for the rest of the process lifetime. So if the code running in that context references anything from that Assembly after it is collected, it would crash the runtime or result in unexpected NullReferenceException, possibly even AccessViolationException and possibly other kinds of bad behavior.

Recommended action

Don't return collectible assemblies in AssemblyLoadContext.Load overload or AssemblyLoadContext.Resolving event of a non-collectible AssemblyLoadContext. Possible workaround is to change the AssemblyLoadContext to collectible by passing true in the isCollectible argument to its constructor and then keep a reference to that AssemblyLoadContext forever to make sure it is never collected.

Feature area

Core .NET libraries

Affected APIs

AssemblyLoadContext.Load override
AssemblyLoadContext.Resolving event

Metadata

Metadata

Assignees

Labels

🏁 Release: .NET 7Work items for the .NET 7 releasebinary incompatibleExisting binaries may encounter a breaking change in behavior.breaking-changeIndicates a .NET Core breaking change

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions