fix(plugins): close LA5 ownership races
This commit is contained in:
parent
fbe9c8a288
commit
f820eb258d
14 changed files with 467 additions and 107 deletions
|
|
@ -11,6 +11,8 @@ public static class PluginLoader
|
|||
/// implementing <see cref="IAcDreamPlugin"/>, instantiate it, and call its
|
||||
/// <see cref="IAcDreamPlugin.Initialize"/> with the supplied host. Any failure
|
||||
/// is returned as a failed <see cref="LoadedPlugin"/> rather than thrown.
|
||||
/// A returned partial plugin/context remains caller-owned; this method never
|
||||
/// requests unload because the caller must close host registrations first.
|
||||
/// </summary>
|
||||
public static LoadedPlugin Load(string pluginDirectory, PluginManifest manifest, IPluginHost host)
|
||||
{
|
||||
|
|
@ -48,15 +50,12 @@ public static class PluginLoader
|
|||
|
||||
if (pluginType is null)
|
||||
{
|
||||
var released = new WeakReference(alc);
|
||||
alc.Unload();
|
||||
return new LoadedPlugin(
|
||||
manifest,
|
||||
Plugin: null,
|
||||
LoadContext: null,
|
||||
LoadContext: alc,
|
||||
Error: new InvalidOperationException(
|
||||
$"no IAcDreamPlugin implementation found in {manifest.EntryDll}"),
|
||||
ReleasedLoadContext: released);
|
||||
$"no IAcDreamPlugin implementation found in {manifest.EntryDll}"));
|
||||
}
|
||||
|
||||
instance = (IAcDreamPlugin)Activator.CreateInstance(pluginType)!;
|
||||
|
|
@ -65,20 +64,15 @@ public static class PluginLoader
|
|||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
// Initialize may have attached host callbacks before it failed.
|
||||
// Give that partial instance the same best-effort cleanup chance
|
||||
// as an Enable failure before releasing the collectible context.
|
||||
try { instance?.Disable(); }
|
||||
catch { }
|
||||
WeakReference? released = alc is null ? null : new WeakReference(alc);
|
||||
try { alc?.Unload(); }
|
||||
catch { }
|
||||
// The caller owns rollback for a partial instance/context. In
|
||||
// particular, Initialize may already have attached host callbacks;
|
||||
// the per-plugin host scope must remove those registrations before
|
||||
// Disable or any collectible unload request can run.
|
||||
return new LoadedPlugin(
|
||||
manifest,
|
||||
Plugin: null,
|
||||
LoadContext: null,
|
||||
Error: ex,
|
||||
ReleasedLoadContext: released);
|
||||
Plugin: instance,
|
||||
LoadContext: alc,
|
||||
Error: ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue