Skip to content

Race condition results in Assembly reference equality being false #70742

Closed
@mrvoorhe

Description

Description

I was investigating a random instability running our NUnit tests. The issue traced back to two assembly instances not being equal when I'm pretty sure they should be.

There is a race condition that results in the following randomly being false when multiple threads trigger the loading of an assembly for the first time

static void Worker()
{
    var asm1 = typeof(Class1).Assembly;
    var asm2 = typeof(Class1).Assembly;

    if (asm1 != asm2)
        Console.WriteLine("Assemblies were not equal!!!");
}

When this happens, one of the assembly instances will not appear in AssemblyLoadContext.Default.Assemblies

I was able to reproduce this on both Windows & Mac using .NET 6.0.100.

I was able to reproduce using .NET 5.0.301 on windows. I didn't test Mac. The issue appears to be much more common on net5. Every time I've ran on net5 the issue has happened in less than 10 iterations.

Reproduction Steps

  1. Check out the repro project here https://github.com/mrvoorhe/AssemblyRaceBugRepro

  2. dotnet build

  3. dotnet run --project Runner/Runner.csproj --framework net6.0

  4. Wait for the program to end.

If the issue doesn't happen, there are some parameters you can tweak at the top of Runner/Program.cs that may make it easier to reproduce

Expected behavior

Quiting.  The issue never happened

Actual behavior

Assemblies were not equal!!!
asm1.GetHashCode() = 4032828
asm2.GetHashCode() = 37489757
Default ALC contains asm1 = False
Default ALC contains asm2 = True
Run 76 complete
Quiting because behavior was reproduced

Regression?

The issue does not seem to happen on .NET Framework. I've completed a few thousand iterations without hitting the problem.

I was able to reproduce the issue using .NET 5.0.301 on windows. I didn't test net5 on mac. The issue appears to be much more common on net5. Every time I've ran on net5 the issue has happened in less than 10 iterations.

The repro project has targets setup for net5.0 and net48

Known Workarounds

I used

public static bool EqualsWorkaroundForInstability(this Assembly assembly, Assembly other)
    {
        return assembly.FullName == other.FullName && assembly.Location == other.Location;
    }

To workaround the issue

Configuration

I reproduced on 6.0.100 and 5.0.301

I reproduced on Windows 11 and macOS Monterey

x64 Windows. M1 Mac Pro.

Other information

No response

Metadata

Assignees

Type

No type

Projects

  • Status

    Done

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions