-
Notifications
You must be signed in to change notification settings - Fork 771
Description
Describe the bug
BehaviorTree.CPP vendors tinyxml2 version 10.0.0. If a library user uses tinyxml2 too, but links to version 11.0.0, it can result in segfaults. This happens when ROS, and specifically nav2_behavior_tree is compiled against tinyxml2 11.0.0. See the backtrace below.
I can see two possible solutions:
- Allow (optional) compilation of BehaviorTree.CPP against system-provided tinyxml2.
- Export the tinyxml2 header and library used by BehaviorTree.CPP so that library users can link to the correct version.
IMO, solution 1 would be simpler.
Backtrace:
#0 0x00007ffff40a85be in __GI___libc_free (mem=0x1) at malloc.c:3375
#1 0x00007ffff64fdde7 in tinyxml2::DynArray<char, 20>::~DynArray (this=0x7fffffff03f0, __in_chrg=<optimized out>)
at /build/behaviortree_cpp_v4-release-release-jazzy-behaviortree_cpp-4.7.1-1/3rdparty/tinyxml2/tinyxml2.h:215
#2 tinyxml2::XMLPrinter::~XMLPrinter (this=0x7fffffff02e0, __in_chrg=<optimized out>) at /build/behaviortree_cpp_v4-release-release-jazzy-behaviortree_cpp-4.7.1-1/3rdparty/tinyxml2/tinyxml2.h:2251
#3 0x00007ffff6431bd1 in BT::XMLParser::PImpl::loadDocImpl (this=<optimized out>, doc=<optimized out>, add_includes=add_includes@entry=true)
at /nix/store/2agih0y5ns3sgbviw2xhivdgg59b41g9-gcc-14-20241116/include/c++/14-20241116/bits/allocator.h:182
#4 0x00007ffff64fbda8 in BT::XMLParser::loadFromFile (this=<optimized out>, filepath=..., add_includes=true)
at /build/behaviortree_cpp_v4-release-release-jazzy-behaviortree_cpp-4.7.1-1/src/xml_parsing.cpp:164
#5 0x00007ffff6473309 in BT::BehaviorTreeFactory::createTreeFromFile (this=0xbcaf28, file_path=..., blackboard=...)
at /build/behaviortree_cpp_v4-release-release-jazzy-behaviortree_cpp-4.7.1-1/src/bt_factory.cpp:366
#6 0x00007ffff7ec3f96 in nav2_behavior_tree::BehaviorTreeEngine::createTreeFromFile(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, std::shared_ptr<BT::Blackboard>) () from /nix/store/n5f670fwvkp9f34hq0fm8gcb7b0clqk3-ros-env/lib/libnav2_behavior_tree.so
#7 0x00007fffe67a6912 in nav2_behavior_tree::BtActionServer<nav2_msgs::action::NavigateToPose>::loadBehaviorTree (this=this@entry=0x6981e0, bt_xml_filename=...)
at /nix/store/c25zd27c7w79gca25qbsq6cdz0fvxlqv-ros-jazzy-nav2-behavior-tree-1.3.9-r1/include/nav2_behavior_tree/bt_action_server_impl.hpp:246
#8 0x00007fffe67b8101 in nav2_behavior_tree::BtActionServer<nav2_msgs::action::NavigateToPose>::on_activate (this=0x6981e0)
at /nix/store/c25zd27c7w79gca25qbsq6cdz0fvxlqv-ros-jazzy-nav2-behavior-tree-1.3.9-r1/include/nav2_behavior_tree/bt_action_server_impl.hpp:195
#9 0x00007fffe67b82d2 in nav2_core::BehaviorTreeNavigator<nav2_msgs::action::NavigateToPose>::on_activate (this=0xa148f0)
at /nix/store/avdw81296sr8l0k9nplvzrmdcg59mg3i-ros-jazzy-nav2-core-1.3.9-r1/include/nav2_core/behavior_tree_navigator.hpp:239
#10 0x00007ffff4d9b869 in nav2_bt_navigator::BtNavigator::on_activate (this=0x5e22a0, state=...) at /build/navigation2-release-release-jazzy-nav2_bt_navigator-1.3.9-1/src/bt_navigator.cpp:149
#11 0x00007ffff547e593 in std::function<rclcpp_lifecycle::node_interfaces::LifecycleNodeInterface::CallbackReturn(rclcpp_lifecycle::State const&)>::operator() (this=0x7fffffff2530, __args#0=...)
at /nix/store/2agih0y5ns3sgbviw2xhivdgg59b41g9-gcc-14-20241116/include/c++/14-20241116/bits/std_function.h:591
#12 rclcpp_lifecycle::LifecycleNode::LifecycleNodeInterfaceImpl::execute_callback (this=this@entry=0x8ceba0, cb_id=cb_id@entry=13, previous_state=...)
at /build/rclcpp-release-release-jazzy-rclcpp_lifecycle-28.1.12-1/src/lifecycle_node_interface_impl.cpp:514
#13 0x00007ffff547e985 in rclcpp_lifecycle::LifecycleNode::LifecycleNodeInterfaceImpl::change_state (this=this@entry=0x8ceba0, transition_id=transition_id@entry=3 '\003',
cb_return_code=@0x7fffffff3887: 0) at /build/rclcpp-release-release-jazzy-rclcpp_lifecycle-28.1.12-1/src/lifecycle_node_interface_impl.cpp:447
#14 0x00007ffff547f325 in rclcpp_lifecycle::LifecycleNode::LifecycleNodeInterfaceImpl::on_change_state (this=0x8ceba0, header=..., req=..., resp=...)
at /build/rclcpp-release-release-jazzy-rclcpp_lifecycle-28.1.12-1/src/lifecycle_node_interface_impl.cpp:242
#15 0x00007ffff5481d28 in std::__invoke_impl<void, void (rclcpp_lifecycle::LifecycleNode::LifecycleNodeInterfaceImpl::*&)(std::shared_ptr<rmw_request_id_s>, std::shared_ptr<lifecycle_msgs::srv::ChangeState_Request_<std::allocator<void> > >, std::shared_ptr<lifecycle_msgs::srv::ChangeState_Response_<std::allocator<void> > >), rclcpp_lifecycle::LifecycleNode::LifecycleNodeInterfaceImpl*&, std::shared_ptr<rmw_request_id_s>, std::shared_ptr<lifecycle_msgs::srv::ChangeState_Request_<std::allocator<void> > >, std::shared_ptr<lifecycle_msgs::srv::ChangeState_Response_<std::allocator<void> > > > (
__f=<optimized out>, __t=<optimized out>) at /nix/store/2agih0y5ns3sgbviw2xhivdgg59b41g9-gcc-14-20241116/include/c++/14-20241116/bits/invoke.h:74
#16 std::__invoke<void (rclcpp_lifecycle::LifecycleNode::LifecycleNodeInterfaceImpl::*&)(std::shared_ptr<rmw_request_id_s>, std::shared_ptr<lifecycle_msgs::srv::ChangeState_Request_<std::allocator<void> > >, std::shared_ptr<lifecycle_msgs::srv::ChangeState_Response_<std::allocator<void> > >), rclcpp_lifecycle::LifecycleNode::LifecycleNodeInterfaceImpl*&, std::shared_ptr<rmw_request_id_s>, std::shared_ptr<lifecycle_msgs::srv::ChangeState_Request_<std::allocator<void> > >, std::shared_ptr<lifecycle_msgs::srv::ChangeState_Response_<std::allocator<void> > > > (__fn=<optimized out>)
at /nix/store/2agih0y5ns3sgbviw2xhivdgg59b41g9-gcc-14-20241116/include/c++/14-20241116/bits/invoke.h:96
#17 std::_Bind<void (rclcpp_lifecycle::LifecycleNode::LifecycleNodeInterfaceImpl::*(rclcpp_lifecycle::LifecycleNode::LifecycleNodeInterfaceImpl*, std::_Placeholder<1>, std::_Placeholder<2>, std::_Placeholder<3>))(std::shared_ptr<rmw_request_id_s>, std::shared_ptr<lifecycle_msgs::srv::ChangeState_Request_<std::allocator<void> > >, std::shared_ptr<lifecycle_msgs::srv::ChangeState_Response_<std::allocator<void> > >)>::__call<void, std::shared_ptr<rmw_request_id_s>&&, std::shared_ptr<lifecycle_msgs::srv::ChangeState_Request_<std::allocator<void> > >&&, std::shared_ptr<lifecycle_msgs::srv::ChangeState_Response_<std::allocator<void> > >&&, 0ul, 1ul, 2ul, 3ul>(std::tuple<std::shared_ptr<rmw_request_id_s>&&, std::shared_ptr<lifecycle_msgs::srv::ChangeState_Request_<std::allocator<void> > >&&, std::shared_ptr<lifecycle_msgs::srv::ChangeState_Response_<std::allocator<void> > >&&>&&, std::_Index_tuple<0ul, 1ul, 2ul, 3ul>) (this=<optimized out>, __args=...)
at /nix/store/2agih0y5ns3sgbviw2xhivdgg59b41g9-gcc-14-20241116/include/c++/14-20241116/functional:513
How to Reproduce
The bug and its reproducer was originally reported in lopsided98/nix-ros-overlay#648. The summary is:
Compile nav2_behavior_tree
against tinyxml2 11.0.0 and run:
- Terminal 1:
ros2 run --prefix "gdb -ex run --args" nav2_bt_navigator bt_navigator
- Terminal 2:
ros2 run nav2_util lifecycle_bringup bt_navigator
Observe bt_navigator segfault.
This can be easily reproduced with the Nix package manager by using the following flake.nix
, running nix develop
(perhaps with --experimental-features 'nix-command flakes'
) and then the above commands.
{
inputs = {
nix-ros-overlay.url = "github:lopsided98/nix-ros-overlay/730baddd51dff4e1e59b7dfa871ca234e9d95df4";
nixpkgs.follows = "nix-ros-overlay/nixpkgs";
};
outputs = { self, nix-ros-overlay, nixpkgs }:
nix-ros-overlay.inputs.flake-utils.lib.eachDefaultSystem (system:
let
pkgs = import nixpkgs { inherit system; overlays = [ nix-ros-overlay.overlays.default ]; };
in {
devShells.default = pkgs.mkShell {
name = "Example project";
packages = [
pkgs.colcon
(with pkgs.rosPackages.jazzy; buildEnv {
paths = [ nav2-bt-navigator nav2-util ros-core ];
})
];
};
});
nixConfig = {
extra-substituters = [ "https://ros.cachix.org" ];
extra-trusted-public-keys = [ "ros.cachix.org-1:dSyZxI8geDCJrwgvCOHDoAfOm5sV1wCPjBkKL+38Rvo=" ];
};
}