From aea62732e5ce9add17dbe7da5864b2c54753b1b4 Mon Sep 17 00:00:00 2001 From: Haselnussbomber Date: Tue, 22 Apr 2025 16:34:19 +0200 Subject: [PATCH] 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 --- Dalamud/Game/Addon/Events/AddonEventManager.cs | 9 ++++++--- .../Game/Addon/Events/PluginEventController.cs | 15 ++++++++------- 2 files changed, 14 insertions(+), 10 deletions(-) diff --git a/Dalamud/Game/Addon/Events/AddonEventManager.cs b/Dalamud/Game/Addon/Events/AddonEventManager.cs index dce2a7e73..a7241dd58 100644 --- a/Dalamud/Game/Addon/Events/AddonEventManager.cs +++ b/Dalamud/Game/Addon/Events/AddonEventManager.cs @@ -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.Get().RunOnFrameworkThread(() => + { + this.eventManagerService.RemovePluginEventController(this.plugin.EffectiveWorkingPluginId); + }).Wait(); } /// diff --git a/Dalamud/Game/Addon/Events/PluginEventController.cs b/Dalamud/Game/Addon/Events/PluginEventController.cs index 403a812db..f32c7ad8f 100644 --- a/Dalamud/Game/Addon/Events/PluginEventController.cs +++ b/Dalamud/Game/Addon/Events/PluginEventController.cs @@ -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; } }