rclpy
rclpy copied to clipboard
Crash on shutdown: rcl_shutdown already called on the given context
Bug report
Required Info:
- Operating System:
- Ubuntu 22.04.1 LTS
- Installation type:
- binaries
- Version or commit hash:
- rclpy 3.3.7
- DDS implementation:
- rmw_fastrtps_cpp
- Client library (if applicable):
- rqt_reconfigure v 1.1.1, rqt_gui_py v1.1.4, qt_gui v2.2.2
Steps to reproduce issue
ros2 run rqt_reconfigure rqt_reconfigure
CTRL+C
Similar behavior is seen when running rqt_graph
Expected behavior
Shutdown without errors, which is seen when clicking on the cross of the GUI.
Actual behavior
The following errors are printed:
PluginHandler.shutdown_plugin() plugin "rqt_graph/RosGraph#0" raised an exception:
Traceback (most recent call last):
File "/home/noblean/ros_ws/install/qt_gui/local/lib/python3.10/dist-packages/qt_gui/plugin_handler.py", line 137, in shutdown_plugin
self._shutdown_plugin()
File "/home/noblean/ros_ws/install/qt_gui/local/lib/python3.10/dist-packages/qt_gui/plugin_handler_direct.py", line 92, in _shutdown_plugin
self.emit_shutdown_plugin_completed()
File "/home/noblean/ros_ws/install/qt_gui/local/lib/python3.10/dist-packages/qt_gui/plugin_handler.py", line 151, in emit_shutdown_plugin_completed
callback(self._instance_id)
File "/home/noblean/ros_ws/install/qt_gui/local/lib/python3.10/dist-packages/qt_gui/plugin_manager.py", line 480, in _close_application_shutdown_callback
self._close_application_signal()
File "/home/noblean/ros_ws/install/qt_gui/local/lib/python3.10/dist-packages/qt_gui/plugin_manager.py", line 483, in _close_application_signal
self._plugin_provider.shutdown()
File "/home/noblean/ros_ws/install/qt_gui/local/lib/python3.10/dist-packages/qt_gui/composite_plugin_provider.py", line 87, in shutdown
plugin_provider.shutdown()
File "/home/noblean/ros_ws/install/qt_gui/local/lib/python3.10/dist-packages/qt_gui/composite_plugin_provider.py", line 87, in shutdown
plugin_provider.shutdown()
File "/home/noblean/ros_ws/build/rqt_gui_py/src/rqt_gui_py/ros_py_plugin_provider.py", line 65, in shutdown
self._destroy_node()
File "/home/noblean/ros_ws/build/rqt_gui_py/src/rqt_gui_py/ros_py_plugin_provider.py", line 100, in _destroy_node
rclpy.shutdown()
File "/home/noblean/ros_ws/install/rclpy/local/lib/python3.10/dist-packages/rclpy/__init__.py", line 126, in shutdown
_shutdown(context=context)
File "/home/noblean/ros_ws/install/rclpy/local/lib/python3.10/dist-packages/rclpy/utilities.py", line 58, in shutdown
return context.shutdown()
File "/home/noblean/ros_ws/install/rclpy/local/lib/python3.10/dist-packages/rclpy/context.py", line 103, in shutdown
self.__context.shutdown()
rclpy._rclpy_pybind11.RCLError: failed to shutdown: rcl_shutdown already called on the given context, at ./src/rcl/init.c:241
Additional information and considerations
I have been playing around a bit with this issue.
- When commenting out rclpy.shutdown() in this file the issue did not show up
- Calling rclpy.ok() before the same line gave different results for stopping rqt_reconfigure with CTRL+C versus stopping it with by clicking on the cross in the GUI.
Thanks for reporting, and the initial investigation. I think that this is relatively consistent across the uses of rclpy. I believe I have some time to look into this in the near future.
After some inspection, here are some (unordered) thoughts about what is going on here.
rqt installs a global signal handler as part of the rclcpp::init call in RosCppPluginProvider: https://github.com/ros-visualization/rqt/blob/568d8fa2d971698a5dea0fb678448f7bd5d0c5e5/rqt_gui_cpp/src/rqt_gui_cpp/roscpp_plugin_provider.cpp#L93-L97
The python plugin in question (in this case rqt_reconfigure) also installs it's global signal handler.
What we are seeing is that both c++ and python are calling shutdown on the context, without being aware of the other implementation doing the same.
I think that my general strategy forward is to make RosCppPluginProvider pass it's initialized context forward to the plugins, and prevent the plugins themselves from performing shutdown calls on that context, instead leaving it to the provider.
Can we use try_shutdown instead, https://github.com/ros-visualization/rqt/blob/6cf57076b8501264497fd7355997335b3d05d511/rqt_gui_py/src/rqt_gui_py/ros_py_plugin_provider.py#L89 ?