Skip to content

Microsoft.Build.Shared.MSBuildLoadContext misbehavior #12370

@ericstj

Description

@ericstj

Issue Description

When investigating dotnet/sdk#49531 we found some pretty bad behavior of MSBuildLoadContext.

  1. It doesn't honor framework unification. If a assembly has in its directory a framework assembly (like System.Memory, or System.Text.Json) it will allow that version to be loaded, even if it's older than the shared framework.
  2. It doesn't do roll-forward. If an assembly reference is older than the assembly provided (eg: reference is for 4.0.1.2, and dll shipped is 4.0.2.0) it skips loading it and falls back to the default ALC.

Steps to Reproduce

We reproduced this by SDK testing that specified MSBUILDADDITIONALSDKRESOLVERSFOLDER = C:\h\w\B80C09CA\p\r\Release\net472\SdkResolvers so it was telling MSBuild to load .NET 4.7.2 SDK resolvers for a .NET Core invocation of msbuild. This is a bit of a stretch, but I bet one could construct a similar repro without this accidental mismatch.

Suppose a task has a mix of dependency references and relies on framework unification. That works so long as framework unification produces the same result as task-directory unification. Now imagine that MSBuild is running on a newer framework - it would not longer produce the same result and the task would fail to load.

Expected Behavior

Assembly loads using it's local dependencies only when they are newer than the framework assemblies. Task unifies to either framework assembly or local assembly consistently.

Actual Behavior

Task will use local dependency when older than framework dependency. Task does not unify to local dependency when chosen, will fall back to framework dependency.

Analysis

Version comparison bug here

if (candidateAssemblyName.Version != assemblyName.Version)
{
continue;
}

I'm not sure what the right way is to to probe framework dependencies for a version comparison - today the only thing the ALC does is return null for MSBuild (which doesn't permit a version comparison). It's possible this is not easy/posible without a deps file. I bet @elinor-fung or @agocke could tell us.

Versions & Configurations

No response

Metadata

Metadata

Labels

Priority:2Work that is important, but not critical for the releaseneeds-designRequires discussion with the dev team before attempting a fix.needs-investigationtriaged

Type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions