fix(plugins): close LA5 ownership races

This commit is contained in:
Erik 2026-08-14 19:28:14 +02:00
parent fbe9c8a288
commit f820eb258d
14 changed files with 467 additions and 107 deletions

View file

@ -214,9 +214,11 @@ public sealed class PluginSession : IDisposable
scope);
if (!loaded.Success)
{
// Initialize can register callbacks before it fails. The
// registration transaction closes before plugin cleanup
// and, critically, before any ALC Unloading notification.
scope.Dispose();
if (loaded.ReleasedLoadContext is { } released)
_releasedContexts.Add(released);
ReleaseFailedLoad(loaded);
AddError(
errors,
id,
@ -304,6 +306,42 @@ public sealed class PluginSession : IDisposable
}
}
private void ReleaseFailedLoad(LoadedPlugin loaded)
{
if (loaded.Plugin is not null)
{
try
{
loaded.Plugin.Disable();
}
catch (Exception error)
{
SafeLog(
static (log, message, exception) =>
log.Error(message, exception),
$"plugin cleanup after initialize failure failed: {loaded.Manifest.Id}",
error);
}
}
if (loaded.LoadContext is null)
return;
_releasedContexts.Add(new WeakReference(loaded.LoadContext));
try
{
loaded.LoadContext.Unload();
}
catch (Exception error)
{
SafeLog(
static (log, message, exception) =>
log.Error(message, exception),
$"plugin unload after load failure failed: {loaded.Manifest.Id}",
error);
}
}
private void Report(PluginSessionStatus status)
{
if (_report is null)