From 6ed66ada28dda843e53918b41074e08222f5c8f3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=F0=9F=8E=A7=20RicherTunes=20=F0=9F=8E=A7?= Date: Sun, 4 Jan 2026 19:31:24 -0500 Subject: [PATCH] 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() --- src/NzbDrone.Common/Composition/PluginLoader.cs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/NzbDrone.Common/Composition/PluginLoader.cs b/src/NzbDrone.Common/Composition/PluginLoader.cs index d72aced44..af1725d8f 100644 --- a/src/NzbDrone.Common/Composition/PluginLoader.cs +++ b/src/NzbDrone.Common/Composition/PluginLoader.cs @@ -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 PluginContexts = new (); public static (List, List) LoadPlugins(IEnumerable pluginPaths) { @@ -38,6 +39,7 @@ public static bool UnloadPlugins(List 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 pluginRefs) { if (pluginRef?.Target != null) { - ((PluginLoadContext)pluginRef.Target).Unload(); + var context = (PluginLoadContext)pluginRef.Target; + PluginContexts.Remove(context); + context.Unload(); } } }