Problem
Both CallbackIsolatedExecutor::spin() and ComponentManagerCallbackIsolated::add_node_to_executor() only discover callback groups at the time they are initially called. Any callback groups created after spin() has started (e.g., groups created lazily in timer callbacks or after initialization) are never detected and therefore never assigned dedicated executor threads.
Affected files
callback_isolated_executor/src/callback_isolated_executor.cpp — spin() iterates weak_groups_to_nodes_ and weak_nodes_ once at startup, spawns threads, then blocks on join(). Late-created groups are invisible.
callback_isolated_executor/src/component_container_callback_isolated.cpp — add_node_to_executor() runs for_each_callback_group() once when a node is loaded. Groups created after this point are missed.
Proposed Solution
Implement a polling-based monitoring mechanism that periodically scans for newly created callback groups, similar to the approach taken in the agnocast repository:
Key design points (from the agnocast implementation)
- A configurable polling interval (default 100ms) via
monitor_polling_interval_ms parameter
- Extracted thread-spawning logic into a reusable helper for consistent handling of both startup and dynamically-created groups
rclcpp::ok() checks to prevent executor creation after context shutdown
- Proper thread lifecycle management (joining child threads during cleanup)
References
Problem
Both
CallbackIsolatedExecutor::spin()andComponentManagerCallbackIsolated::add_node_to_executor()only discover callback groups at the time they are initially called. Any callback groups created afterspin()has started (e.g., groups created lazily in timer callbacks or after initialization) are never detected and therefore never assigned dedicated executor threads.Affected files
callback_isolated_executor/src/callback_isolated_executor.cpp—spin()iteratesweak_groups_to_nodes_andweak_nodes_once at startup, spawns threads, then blocks onjoin(). Late-created groups are invisible.callback_isolated_executor/src/component_container_callback_isolated.cpp—add_node_to_executor()runsfor_each_callback_group()once when a node is loaded. Groups created after this point are missed.Proposed Solution
Implement a polling-based monitoring mechanism that periodically scans for newly created callback groups, similar to the approach taken in the agnocast repository:
CallbackIsolatedAgnocastExecutor::spin(), converting the localthreadsvector to a member variable (child_threads_) to support runtime additions and proper cleanup.Key design points (from the agnocast implementation)
monitor_polling_interval_msparameterrclcpp::ok()checks to prevent executor creation after context shutdownReferences