Skip to content

[BUG] gateway_node segfaults on shutdown when the OPC UA plugin is loaded #659

Description

@bburda

Bug report

Steps to reproduce

  1. Build with colcon build --symlink-install --packages-up-to ros2_medkit_opcua ros2_medkit_gateway (Jazzy dev image).
  2. Start the gateway with the plugin loaded and no server listening:
    OPCUA_ENDPOINT_URL=opc.tcp://127.0.0.1:14840 OPCUA_NODE_MAP_PATH=<tank_demo_nodes.yaml> OPCUA_DISCOVERY_ENABLED=0 \
    gateway_node --ros-args --params-file docker/gateway_params.yaml \
      -p plugins.opcua.path:=<install>/ros2_medkit_opcua/lib/ros2_medkit_opcua/libros2_medkit_opcua_plugin.so
    
  3. Wait 10 s, send SIGTERM, read the exit code.

Control: the same params with the plugins key removed.

Expected behavior

A clean exit (0) on SIGTERM, with or without the plugin.

Actual behavior

Exit 139 whenever the plugin is loaded, 3 of 3 runs on main at 8b1969f (0.7.0). Without the plugin the same teardown exits 0, 3 of 3. The crash lands in the node destructor (node.reset() in main.cpp) after the plugin has already logged OPC-UA plugin shutdown complete. Discovery was off and the endpoint pointed at a closed port, so the comms-lost path was active and no server was involved.

Thread 1 "gateway_node" received signal SIGSEGV, Segmentation fault.
#0  rclcpp::CallbackGroup::~CallbackGroup ()          from librclcpp.so
#2  rclcpp::node_interfaces::NodeBase::~NodeBase ()    from librclcpp.so
#5  rclcpp::Node::~Node ()                             from librclcpp.so
#6  std::_Sp_counted_base<...>::_M_release_last_use_cold ()
#7  main ()

Every docker stop of a gateway with the plugin ends in a core dump instead of a clean exit, which hides real shutdown problems behind a constant one and makes exit codes useless for supervisors.

Environment

  • ros2_medkit version: 0.7.0 (main at 8b1969f)
  • ROS 2 distro: Jazzy
  • OS: Ubuntu 24.04 (the dev container)

Additional information

Unconfirmed hypothesis: PluginLoader loads the plugin RTLD_NOW | RTLD_LOCAL and dlcloses it before the node's callback groups are destroyed, so a callback group still referencing callables from the unloaded .so is torn down last. Keeping the handle open until after node.reset(), or destroying the plugin's callback groups in the plugin's own shutdown, would test that.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions