From 12b819b5b7ef46893f167e864f429775718a576b Mon Sep 17 00:00:00 2001 From: Aysha Afrah Ziya Date: Fri, 24 Jul 2026 15:41:05 +0530 Subject: [PATCH] fix use-after-free of the timer node mutex on destruction --- include/behaviortree_cpp/actions/sleep_node.h | 4 +++- include/behaviortree_cpp/decorators/delay_node.h | 4 +++- include/behaviortree_cpp/decorators/timeout_node.h | 4 +++- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/include/behaviortree_cpp/actions/sleep_node.h b/include/behaviortree_cpp/actions/sleep_node.h index 8ab31e9f7..337bf9a27 100644 --- a/include/behaviortree_cpp/actions/sleep_node.h +++ b/include/behaviortree_cpp/actions/sleep_node.h @@ -40,11 +40,13 @@ class SleepNode : public StatefulActionNode } private: - TimerQueue<> timer_; uint64_t timer_id_ = 0; std::atomic_bool timer_waiting_ = false; std::mutex delay_mutex_; + // Keep last: ~TimerQueue() joins the worker thread, so this must be destroyed + // before delay_mutex_ and timer_waiting_, which the timer handler touches. + TimerQueue<> timer_; }; } // namespace BT diff --git a/include/behaviortree_cpp/decorators/delay_node.h b/include/behaviortree_cpp/decorators/delay_node.h index 6bbe4f997..e1e610ddc 100644 --- a/include/behaviortree_cpp/decorators/delay_node.h +++ b/include/behaviortree_cpp/decorators/delay_node.h @@ -65,7 +65,6 @@ class DelayNode : public DecoratorNode void halt() override; private: - TimerQueue<> timer_; uint64_t timer_id_; virtual BT::NodeStatus tick() override; @@ -76,6 +75,9 @@ class DelayNode : public DecoratorNode unsigned msec_; bool read_parameter_from_ports_; std::mutex delay_mutex_; + // Keep last: ~TimerQueue() joins the worker thread, so this must be destroyed + // before delay_mutex_, which the timer handler locks. + TimerQueue<> timer_; }; } // namespace BT diff --git a/include/behaviortree_cpp/decorators/timeout_node.h b/include/behaviortree_cpp/decorators/timeout_node.h index 2e531470e..1d8518885 100644 --- a/include/behaviortree_cpp/decorators/timeout_node.h +++ b/include/behaviortree_cpp/decorators/timeout_node.h @@ -77,7 +77,6 @@ class TimeoutNode : public DecoratorNode void halt() override; - TimerQueue<> timer_; std::atomic_bool child_halted_ = false; uint64_t timer_id_; @@ -85,6 +84,9 @@ class TimeoutNode : public DecoratorNode bool read_parameter_from_ports_; std::atomic_bool timeout_started_ = false; std::mutex timeout_mutex_; + // Keep last: ~TimerQueue() joins the worker thread, so this must be destroyed + // before timeout_mutex_, which the timer handler locks. + TimerQueue<> timer_; }; } // namespace BT