ros2 actions ai_generated true

ROS2 action goal preemption causes crash or undefined behavior when new goal arrives during execution

ID: ros2/action-server-preemption-race

Also available as: JSON · Markdown
85%Fix Rate
88%Confidence
3Evidence
2023-01-01First Seen

Version Compatibility

VersionStatusIntroducedDeprecatedNotes
any active

Root Cause

ROS2 action servers don't automatically handle goal preemption. When a new goal arrives while executing a previous one, both execute concurrently unless you explicitly implement preemption logic in handle_goal and execute callbacks.

generic

Workarounds

  1. 90% success Use a single-goal policy: reject or queue new goals while one is executing
    def handle_goal(self, goal_handle): if self._executing: return GoalResponse.REJECT; return GoalResponse.ACCEPT
  2. 88% success Implement preemption with threading lock in execute callback
    In execute: periodically check if goal_handle.is_cancel_requested or if a new goal has been accepted. Clean up and return CANCELED.
  3. 85% success Use goal_handle.status to track and manage concurrent goals explicitly
    Maintain a list of active goal handles. In handle_goal, cancel previous goals and wait for their execute callbacks to finish.

Dead Ends

Common approaches that don't work:

  1. Assume new goals automatically cancel previous goals 90% fail

    Unlike ROS1 actionlib, ROS2 action servers do NOT auto-preempt. Multiple goals execute simultaneously unless you explicitly manage goal lifecycle.

  2. Cancel the previous goal in handle_goal callback 82% fail

    handle_goal is called before the new goal starts executing. Canceling the old goal here creates a race condition if the old execute callback hasn't checked for cancellation yet.