# rclcpp: Deadlock detected: callback waiting for another callback in same MutuallyExclusiveCallbackGroup

- **ID:** `ros2/rclcpp-dual-mode-callback-group-deadlock`
- **Domain:** ros2
- **Category:** runtime_error
- **Verification:** ai_generated
- **Fix Rate:** 85%

## 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.

## Version Compatibility

| Version | Status | Introduced | Deprecated |
|---------|--------|------------|------------|
| ROS2 Humble (rclcpp 16.0.0) | active | — | — |
| ROS2 Iron (rclcpp 17.0.0) | active | — | — |
| ROS2 Rolling (rclcpp 18.0.0) | active | — | — |

## Workarounds

1. **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);** (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);
   ```
2. **Use async service clients to avoid blocking the callback entirely: auto future = client->async_send_request(request);** (85% success)
   ```
   Use async service clients to avoid blocking the callback entirely: auto future = client->async_send_request(request);
   ```

## Dead Ends

- **Increase the callback group's thread count or use a ReentrantCallbackGroup** — Reentrant allows concurrent execution but does not solve the logical dependency; the service call still blocks. (60% fail)
- **Add a sleep or yield in the callback** — Sleeping does not release the callback group lock; the deadlock persists. (95% fail)
