goatcorp / Dalamud

FFXIV plugin framework and API
GNU Affero General Public License v3.0
1.12k stars 264 forks source link

AddonLifeCycle crashing client on Pre/Post ReceiveEvent #1508

Closed ItsBexy closed 8 months ago

ItsBexy commented 9 months ago

I'm running into an issue using AddonEvent.PostReceiveEvent with certain addons. If I set up a PreReceiveEvent or PostReceiveEvent listener like this:

AddonLifecycle.RegisterListener(AddonEvent.PostReceiveEvent, "_ActionBar01", ReceiveEventHandler);

With a simple handler like this:

public static void ReceiveEventHandler(AddonEvent type, AddonArgs args)
{
    try
    {
        Log.Info(args.AddonName);
    }
    catch (Exception ex)
    {
        Log.Error($"Exception:\n{ex}");
    }
}

It will work fine for events on _ActionBar01, but will cause an instantaneous CTD when there's an event on any other hotbar, even if I didn't register a listener for any of them.

The stack overflow looks like this:

Stack overflow.
   at System.Collections.Generic.List`1[[System.__Canon, System.Private.CoreLib, Version=7.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]].GetEnumerator()
   at System.Linq.Enumerable+WhereListIterator`1[[System.__Canon, System.Private.CoreLib, Version=7.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]].MoveNext()
   at Dalamud.Game.Addon.Lifecycle.AddonLifecycle.InvokeListeners(Dalamud.Game.Addon.Lifecycle.AddonEvent, Dalamud.Game.Addon.Lifecycle.AddonArgTypes.AddonArgs)
   at Dalamud.Game.Addon.Lifecycle.AddonLifecycle.OnReceiveEvent(FFXIVClientStructs.FFXIV.Component.GUI.AtkUnitBase*, FFXIVClientStructs.FFXIV.Component.GUI.AtkEventType, Int32, FFXIVClientStructs.FFXIV.Component.GUI.AtkEvent*, IntPtr)
   at Dalamud.Game.Addon.Lifecycle.AddonLifecycle.OnReceiveEvent(FFXIVClientStructs.FFXIV.Component.GUI.AtkUnitBase*, FFXIVClientStructs.FFXIV.Component.GUI.AtkEventType, Int32, FFXIVClientStructs.FFXIV.Component.GUI.AtkEvent*, IntPtr)
   at Dalamud.Game.Addon.Lifecycle.AddonLifecycle.OnReceiveEvent(FFXIVClientStructs.FFXIV.Component.GUI.AtkUnitBase*, FFXIVClientStructs.FFXIV.Component.GUI.AtkEventType, Int32, FFXIVClientStructs.FFXIV.Component.GUI.AtkEvent*, IntPtr)
   at Dalamud.Game.Addon.Lifecycle.AddonLifecycle.OnReceiveEvent(FFXIVClientStructs.FFXIV.Component.GUI.AtkUnitBase*, FFXIVClientStructs.FFXIV.Component.GUI.AtkEventType, Int32, FFXIVClientStructs.FFXIV.Component.GUI.AtkEvent*, IntPtr)
   at Dalamud.Game.Addon.Lifecycle.AddonLifecycle.OnReceiveEvent(FFXIVClientStructs.FFXIV.Component.GUI.AtkUnitBase*, FFXIVClientStructs.FFXIV.Component.GUI.AtkEventType, Int32, FFXIVClientStructs.FFXIV.Component.GUI.AtkEvent*, IntPtr)
   at Dalamud.Game.Addon.Lifecycle.AddonLifecycle.OnReceiveEvent(FFXIVClientStructs.FFXIV.Component.GUI.AtkUnitBase*, FFXIVClientStructs.FFXIV.Component.GUI.AtkEventType, Int32, FFXIVClientStructs.FFXIV.Component.GUI.AtkEvent*, IntPtr)

...and so on for a couple hundred lines.

@MidoriKami

MidoriKami commented 9 months ago

It seems like they share the same listener, which somewhat makes since as they are all implementations of AddonActionBarBase.

I still assert that AddonLifecycle is for basic uses and for anything advanced you'll need to hook things yourself like always.

I don't think there's anything I can really do to stop things like this from happening.

ItsBexy commented 9 months ago

I'm not sure I have an especially advanced use-case; listen for ReceiveEvent, check the type, call one of my plugin's methods if it's a certain type. Not much happening inside the handler.

I'm content to stick with the hook that I currently use for this functionality, but a guardrail or blacklist for addons which share listeners might be appropriate.