From 60142b191ded8a44270e8dfabacf378b2c22a5ec Mon Sep 17 00:00:00 2001 From: Serhii Snitsaruk Date: Sun, 22 Sep 2024 13:57:15 +0200 Subject: [PATCH] Fix invalid access crash on exit in LimboHSM Since #131, `LimboState::_exit()` became a source of potential crashes if object references are used without a validity check. It's too easy to miss this, which can lead to game crashing during runtime. This fix reverts #131 change and proposes alternative approach of re-activating root HSM upon tree entering if it was previously active. Note that it's not an ideal solution, as some state will be lost upon re-parenting: HSM exits and then re-activates and enters its initial state. --- hsm/limbo_hsm.cpp | 15 +++++++++++++++ hsm/limbo_hsm.h | 1 + hsm/limbo_state.cpp | 5 ----- 3 files changed, 16 insertions(+), 5 deletions(-) diff --git a/hsm/limbo_hsm.cpp b/hsm/limbo_hsm.cpp index d6c7ecd..52730d2 100644 --- a/hsm/limbo_hsm.cpp +++ b/hsm/limbo_hsm.cpp @@ -263,6 +263,21 @@ void LimboHSM::_validate_property(PropertyInfo &p_property) const { void LimboHSM::_notification(int p_what) { switch (p_what) { case NOTIFICATION_POST_ENTER_TREE: { + if (was_active && is_root()) { + // Re-activate the root HSM if it was previously active. + // Typically, this happens when the node is re-entered scene repeatedly (e.g., re-parenting, pooling). + set_active(true); + } + } break; + case NOTIFICATION_EXIT_TREE: { + if (is_root()) { + // Remember active status for re-parenting and exit state machine + // to release resources and signal connections if active. + was_active = active; + if (is_active()) { + _exit(); + } + } } break; case NOTIFICATION_PROCESS: { _update(get_process_delta_time()); diff --git a/hsm/limbo_hsm.h b/hsm/limbo_hsm.h index f0e14a1..f7890c1 100644 --- a/hsm/limbo_hsm.h +++ b/hsm/limbo_hsm.h @@ -55,6 +55,7 @@ private: LimboState *previous_active; LimboState *next_active; bool updating = false; + bool was_active = false; HashMap transitions; diff --git a/hsm/limbo_state.cpp b/hsm/limbo_state.cpp index 69b2426..99791dd 100644 --- a/hsm/limbo_state.cpp +++ b/hsm/limbo_state.cpp @@ -190,11 +190,6 @@ void LimboState::_notification(int p_what) { _update_blackboard_plan(); } } break; - case NOTIFICATION_PREDELETE: { - if (is_active()) { - _exit(); - } - } break; } }