diff options
Diffstat (limited to 'modules/mono/glue/GodotSharp/GodotPlugins/Main.cs')
-rw-r--r-- | modules/mono/glue/GodotSharp/GodotPlugins/Main.cs | 44 |
1 files changed, 25 insertions, 19 deletions
diff --git a/modules/mono/glue/GodotSharp/GodotPlugins/Main.cs b/modules/mono/glue/GodotSharp/GodotPlugins/Main.cs index 2a72b7c53e..6117ae17ea 100644 --- a/modules/mono/glue/GodotSharp/GodotPlugins/Main.cs +++ b/modules/mono/glue/GodotSharp/GodotPlugins/Main.cs @@ -21,6 +21,13 @@ namespace GodotPlugins private sealed class PluginLoadContextWrapper { private PluginLoadContext? _pluginLoadContext; + private readonly WeakReference _weakReference; + + private PluginLoadContextWrapper(PluginLoadContext pluginLoadContext, WeakReference weakReference) + { + _pluginLoadContext = pluginLoadContext; + _weakReference = weakReference; + } public string? AssemblyLoadedPath { @@ -31,7 +38,14 @@ namespace GodotPlugins public bool IsCollectible { [MethodImpl(MethodImplOptions.NoInlining)] - get => _pluginLoadContext?.IsCollectible ?? false; + // if _pluginLoadContext is null we already started unloading, so it was collectible + get => _pluginLoadContext?.IsCollectible ?? true; + } + + public bool IsAlive + { + [MethodImpl(MethodImplOptions.NoInlining)] + get => _weakReference.IsAlive; } [MethodImpl(MethodImplOptions.NoInlining)] @@ -43,20 +57,14 @@ namespace GodotPlugins bool isCollectible ) { - var wrapper = new PluginLoadContextWrapper(); - wrapper._pluginLoadContext = new PluginLoadContext( - pluginPath, sharedAssemblies, mainLoadContext, isCollectible); - var assembly = wrapper._pluginLoadContext.LoadFromAssemblyName(assemblyName); + var context = new PluginLoadContext(pluginPath, sharedAssemblies, mainLoadContext, isCollectible); + var reference = new WeakReference(context, trackResurrection: true); + var wrapper = new PluginLoadContextWrapper(context, reference); + var assembly = context.LoadFromAssemblyName(assemblyName); return (assembly, wrapper); } [MethodImpl(MethodImplOptions.NoInlining)] - public WeakReference CreateWeakReference() - { - return new WeakReference(_pluginLoadContext, trackResurrection: true); - } - - [MethodImpl(MethodImplOptions.NoInlining)] internal void Unload() { _pluginLoadContext?.Unload(); @@ -165,7 +173,7 @@ namespace GodotPlugins if (_editorApiAssembly == null) throw new InvalidOperationException("The Godot editor API assembly is not loaded."); - var (assembly, _) = LoadPlugin(assemblyPath, isCollectible: _editorHint); + var (assembly, _) = LoadPlugin(assemblyPath, isCollectible: false); NativeLibrary.SetDllImportResolver(assembly, _dllImportResolver!); @@ -236,32 +244,29 @@ namespace GodotPlugins Console.WriteLine("Unloading assembly load context..."); - var alcWeakReference = pluginLoadContext.CreateWeakReference(); - pluginLoadContext.Unload(); - pluginLoadContext = null; int startTimeMs = Environment.TickCount; bool takingTooLong = false; - while (alcWeakReference.IsAlive) + while (pluginLoadContext.IsAlive) { GC.Collect(GC.MaxGeneration, GCCollectionMode.Forced); GC.WaitForPendingFinalizers(); - if (!alcWeakReference.IsAlive) + if (!pluginLoadContext.IsAlive) break; int elapsedTimeMs = Environment.TickCount - startTimeMs; - if (!takingTooLong && elapsedTimeMs >= 2000) + if (!takingTooLong && elapsedTimeMs >= 200) { takingTooLong = true; // TODO: How to log from GodotPlugins? (delegate pointer?) Console.Error.WriteLine("Assembly unloading is taking longer than expected..."); } - else if (elapsedTimeMs >= 5000) + else if (elapsedTimeMs >= 1000) { // TODO: How to log from GodotPlugins? (delegate pointer?) Console.Error.WriteLine( @@ -273,6 +278,7 @@ namespace GodotPlugins Console.WriteLine("Assembly load context unloaded successfully."); + pluginLoadContext = null; return true; } catch (Exception e) |