You've already forked godot
mirror of
https://github.com/godotengine/godot.git
synced 2025-11-10 13:00:37 +00:00
C#: Fix editor integration breaking and causing error spam when reloading assemblies fails
- Do not reload scripts from non-collectible assemblies - Do not load GodotTools as collectible - Do not attempt to reload the same project assembly forever
This commit is contained in:
@@ -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,19 +57,13 @@ 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()
|
||||
{
|
||||
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user