ros2
runtime_error
ai_generated
true
rclcpp: Deadlock detected: callback waiting for another callback in same MutuallyExclusiveCallbackGroup
ID: ros2/rclcpp-dual-mode-callback-group-deadlock
85%Fix Rate
90%Confidence
1Evidence
2024-01-10First Seen
Version Compatibility
| Version | Status | Introduced | Deprecated | Notes |
|---|---|---|---|---|
| ROS2 Humble (rclcpp 16.0.0) | active | — | — | — |
| ROS2 Iron (rclcpp 17.0.0) | active | — | — | — |
| ROS2 Rolling (rclcpp 18.0.0) | active | — | — | — |
Root Cause
A callback in a MutuallyExclusiveCallbackGroup is blocking on a service or action call that requires another callback in the same group, causing a deadlock because the group only allows one callback at a time.
generic中文
互斥回调组中的某个回调阻塞在需要同一组中另一个回调的服务或动作调用上,导致死锁,因为该组一次只允许一个回调执行。
Official Documentation
https://docs.ros2.org/latest/api/rclcpp/classrclcpp_1_1CallbackGroup.htmlWorkarounds
-
90% success Move the blocking service call to a separate callback group (e.g., a ReentrantCallbackGroup) so it does not block the original group: auto callback_group = this->create_callback_group(rclcpp::CallbackGroupType::Reentrant);
Move the blocking service call to a separate callback group (e.g., a ReentrantCallbackGroup) so it does not block the original group: auto callback_group = this->create_callback_group(rclcpp::CallbackGroupType::Reentrant);
-
85% success Use async service clients to avoid blocking the callback entirely: auto future = client->async_send_request(request);
Use async service clients to avoid blocking the callback entirely: auto future = client->async_send_request(request);
中文步骤
将阻塞的服务调用移动到单独的回调组(例如ReentrantCallbackGroup),使其不会阻塞原始组:auto callback_group = this->create_callback_group(rclcpp::CallbackGroupType::Reentrant);
使用异步服务客户端以避免完全阻塞回调:auto future = client->async_send_request(request);
Dead Ends
Common approaches that don't work:
-
Increase the callback group's thread count or use a ReentrantCallbackGroup
60% fail
Reentrant allows concurrent execution but does not solve the logical dependency; the service call still blocks.
-
Add a sleep or yield in the callback
95% fail
Sleeping does not release the callback group lock; the deadlock persists.