Executors, Callback Groups, and Concurrency in ROS 2¶
Source: ros2-copilot-skills executors skill
Why This Matters¶
When a ROS 2 node feels “randomly blocked,” the problem is often not random at all. It is the executor model. Timers, subscriptions, services, and actions all compete for callback execution, and callback groups determine which work may overlap.
Distilled Takeaways¶
SingleThreadedExecutoris the simplest model, but one slow callback can stall everything else.MultiThreadedExecutoronly helps if callback groups actually allow concurrency.- The default callback group is mutually exclusive, so adding threads alone often changes less than people expect.
- In Python, the GIL limits CPU-bound parallelism even when multiple executor threads exist.
- Reentrant groups increase power and risk at the same time because the same callback may run concurrently.
Practical Guidance¶
- Use separate callback groups when a timer must keep ticking while service or action responses arrive.
- Protect shared state explicitly once true concurrency enters the design.
- Avoid blocking spin helpers inside callbacks unless the executor design has been proven safe.
- Keep concurrency small and reasoned, not decorative.
Corroborating References¶
When to Read the Original Source¶
Go to the original skill when you want explicit callback-group patterns, executor usage examples in Python and C++, and the warning list around the GIL, reentrant groups, and spin-related deadlocks.