dotnet / dotnet/runtime

Debugger preventing AssemblyLoadContext unload

Open
#123,602 7 comments 0 reactions 0 assignees View on GitHub
area-Diagnostics-coreclr
Dominant language
C#
Stars
18.3k
Forks
5.6k
PR merge metrics
PR metrics pending

Description

My ALC unloads fine normally, but fails consistently after I've stepped through code with breakpoints. Unload() + GC just never completes unless I detach first.

I’ve ruled out the usual stuff (static refs, events, threads, GCHandles). Feels like the debugger is holding onto types/metadata once anything gets inspected.

It can be 100% reproduced if you start stepping through the code in the Unload method like this:

```c#
public static bool UnloadPlugin(string assemblyPath)
{
const int warnThresholdMs = 200;
const int timeoutMs = 2000;

TaskTracker.WaitForAllActiveTasks();

string assemblyName = Path.GetFileNameWithoutExtension(assemblyPath);
WeakReference? alcWeak = RemovePlugin(assemblyName);

if (alcWeak == null)
{
LogUnrealSharpPlugins.Log($"Plugin {assemblyName} is not loaded or already removed from registry.");
return true;
}

try
{
LogUnrealSharpPlugins.Log($"Unloading plugin {assemblyName}...");

Stopwatch stopWatch = Stopwatch.StartNew();
bool hasWarned = false;

while (alcWeak.IsAlive)
{
GC.Collect();
GC.WaitForPendingFinalizers();
GC.Collect(GC.MaxGeneration, GCCollectionMode.Forced, true, true);

if (!alcWeak.IsAlive)
{
break;
}

if (!hasWarned && stopWatch.ElapsedMilliseconds >= warnThresholdMs)
{
hasWarned = true;
LogUnrealSharpPlugins.LogError($"Unloading {assemblyName} is taking longer than expected...");
}

if (stopWatch.ElapsedMilliseconds >= timeoutMs)
{
LogUnrealSharpPlugins.LogError($"Failed to unload {assemblyName} within {timeoutMs}ms. Common causes: static references, GCHandles, background threads.");
return false;
}

Thread.Sleep(10);
}

LogUnrealSharpPlugins.Log($"{assemblyName} unloaded successfully in {stopWatch.ElapsedMilliseconds}ms.");
return true;
}
catch (Exception exception)
{
LogUnrealSharpPlugins.LogError($"An error occurred while unloading the plugin: {exception}");
return false;
}
}
```

Has anyone else run into this? Or might have a clue how to solve it?

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.