fix(plugins): Prevent premature GC of PluginLoadContext during multi-plugin load

Keep strong references to PluginLoadContext instances until explicit unload.
Without this, the GC can collect contexts during multi-plugin initialization
causing "AssemblyLoadContext is unloading or was already unloaded" errors.

- Add static PluginContexts list to retain contexts
- Add context to list on load
- Remove from list before Unload()
This commit is contained in:
🎧 RicherTunes 🎧 2026-01-04 19:31:24 -05:00
parent f6a3e73705
commit 6ed66ada28

View file

@ -12,6 +12,7 @@ namespace NzbDrone.Common.Composition
public static class PluginLoader
{
private static readonly Logger Logger = NzbDroneLogger.GetLogger(typeof(PluginLoader));
private static readonly List<PluginLoadContext> PluginContexts = new ();
public static (List<Assembly>, List<WeakReference>) LoadPlugins(IEnumerable<string> pluginPaths)
{
@ -38,6 +39,7 @@ public static bool UnloadPlugins(List<WeakReference> pluginRefs)
private static (Assembly, WeakReference) LoadPlugin(string path)
{
var context = new PluginLoadContext(path);
PluginContexts.Add(context);
var weakRef = new WeakReference(context, trackResurrection: true);
// load from stream to avoid locking on windows
@ -53,7 +55,9 @@ private static void RequestPluginUnload(List<WeakReference> pluginRefs)
{
if (pluginRef?.Target != null)
{
((PluginLoadContext)pluginRef.Target).Unload();
var context = (PluginLoadContext)pluginRef.Target;
PluginContexts.Remove(context);
context.Unload();
}
}
}