Safer AddonEventManager node removal (#2232)

* Remove events on Framework thread

* Make sure the addon is not unloaded

* Cleanup node finding loop

* Wait for PluginEventController to be disposed
This commit is contained in:
Haselnussbomber 2025-04-22 16:34:19 +02:00 committed by GitHub
parent 61a17dac28
commit aea62732e5
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 14 additions and 10 deletions

View file

@ -1,4 +1,4 @@
using System.Collections.Concurrent;
using System.Collections.Concurrent;
using Dalamud.Game.Addon.Lifecycle;
using Dalamud.Game.Addon.Lifecycle.AddonArgTypes;
@ -230,8 +230,11 @@ internal class AddonEventManagerPluginScoped : IInternalDisposableService, IAddo
{
this.eventManagerService.ResetCursor();
}
this.eventManagerService.RemovePluginEventController(this.plugin.EffectiveWorkingPluginId);
Service<Framework>.Get().RunOnFrameworkThread(() =>
{
this.eventManagerService.RemovePluginEventController(this.plugin.EffectiveWorkingPluginId);
}).Wait();
}
/// <inheritdoc/>

View file

@ -1,9 +1,8 @@
using System.Collections.Generic;
using System.Collections.Generic;
using System.Linq;
using Dalamud.Game.Gui;
using Dalamud.Logging.Internal;
using Dalamud.Memory;
using Dalamud.Plugin.Services;
using FFXIVClientStructs.FFXIV.Component.GUI;
@ -139,17 +138,19 @@ internal unsafe class PluginEventController : IDisposable
// Is our stored addon pointer the same as the active addon pointer?
if (currentAddonPointer != eventEntry.Addon) return;
// Does this addon contain the node this event is for? (by address)
// Make sure the addon is not unloaded
var atkUnitBase = (AtkUnitBase*)currentAddonPointer;
if (atkUnitBase->UldManager.LoadedState == AtkLoadState.Unloaded) return;
// Does this addon contain the node this event is for? (by address)
var nodeFound = false;
foreach (var index in Enumerable.Range(0, atkUnitBase->UldManager.NodeListCount))
foreach (var node in atkUnitBase->UldManager.Nodes)
{
var node = atkUnitBase->UldManager.NodeList[index];
// If this node matches our node, then we know our node is still valid.
if (node is not null && (nint)node == eventEntry.Node)
if ((nint)node.Value == eventEntry.Node)
{
nodeFound = true;
break;
}
}