Skip to content

Fix cancelling or killing a task while it is interrupted - #153

Open
HappySamuel wants to merge 1 commit into
open-rmf:mainfrom
HappySamuel:fix/150-cancel-while-interrupted
Open

HappySamuel wants to merge 1 commit into
open-rmf:mainfrom
HappySamuel:fix/150-cancel-while-interrupted

Conversation

@HappySamuel

@HappySamuel HappySamuel commented Oct 21, 2026 •

Copy link
Copy Markdown

Bug fix

Fixed bug

Fixes #150: cancelling or killing a task while it is interrupted leaves the task stuck, and resuming it afterwards restarts the phase that was cancelled.

Must be merged together with open-rmf/rmf_ros2#576 (see "Why two PRs" below).

Fix applied

In Task::Active (rmf_task_sequence), an interrupted task keeps the active phase's Resume in _resume_phase. When the task is then cancelled or killed, the phase finishes, but _begin_next_stage() returns at the interruption check before reaching the code that clears _resume_phase. So:

  • the cancellation sequence (or _finish_task() for a kill) never runs, and
  • resuming the task calls the finished phase's Resume, restarting the cancelled phase.

Changes:

  • _begin_next_stage() clears _resume_phase before the interruption check. Resuming a task whose interrupted phase already finished then moves on to the cancellation sequence or finishes the task. This is what the existing comment ("the phase that we tried to interrupt finished instead of being interrupted") intends.
  • The Resume callback created in interrupt() skips the phase's own Resume when that phase was cancelled or killed.

One thing reviewers should know: a dropped Resume still fires, because Resume triggers on destruction. So events have to ignore a resume that arrives after they finished. The fleet adapter's events did not, so a cancelled GoToPlace would plan its route again. open-rmf/rmf_ros2#576 adds that guard. The mock activity in this repo's tests now behaves the same way.

Tests

Two new cases in test_Sequence.cpp: cancelling an interrupted task, and killing an interrupted task.

without this change with this change
cancel while interrupted, then resume fails: cancellation sequence never starts passes
kill while interrupted, then resume fails: task never finishes passes

Full test_rmf_task_sequence: all tests pass (319 assertions). ament_uncrustify with rmf_code_style.cfg is clean.

Why two PRs

The bug has one half in each repo, and each half alone is worse than today. Measured in rmf_demos (office, jazzy branch) with main of rmf_task and rmf_ros2 built from source on Ubuntu 24.04 / Jazzy. Task A goes to patrol_A2; it is interrupted once the robot moves, then cancelled; task B is sent to the same robot:

after interrupt → cancel A
main A shows canceled, the robot stays on A, B never starts. A manual resume makes the robot drive to A's destination and A ends completed.
this PR only right after the cancel the robot drives to A's destination, A ends completed, B still needs a manual resume
rmf_ros2 PR only A is canceled, the robot stops, but B never starts, even after a resume
both A ends canceled, the robot does not continue to A's destination, B starts immediately and completes, both for a direct robot task and for a dispatched task

GenAI Use

We follow OSRA's policy on GenAI tools

  • I used a GenAI tool in this PR.
  • I did not use GenAI

Generated-by: Claude Code (Claude Opus 5.5) was used to analyse the bug, write the change and tests, run the rmf_demos trials and draft this description. I reviewed the changes and results.

🤖 Generated with Claude Code

When a task is interrupted, Task::Active keeps the active phase's Resume
in _resume_phase. If the task is then cancelled or killed, the active
phase finishes, but _begin_next_stage() returned at the interruption
check before reaching the code that clears _resume_phase. As a result:

* the cancellation sequence (or _finish_task() for a kill) never ran,
  so the task stayed stuck until it was resumed, and
* resuming the task called the finished phase's Resume, restarting the
  phase that had just been cancelled.

Clear _resume_phase before the interruption check, so resuming a task
whose interrupted phase has finished moves on to the cancellation
sequence or finishes the task. In the Resume callback, also skip the
phase's own Resume when that phase was cancelled or killed.

Dropping a stale Resume still triggers it (Resume fires on destruction),
so events must ignore a resume that arrives after they have finished.
The mock activity used by the tests now does that, matching the fleet
adapter events once open-rmf/rmf_ros2 guards them the same way.

Adds tests for cancelling and for killing an interrupted task.

Signed-off-by: HappySamuel <18137963+HappySamuel@users.noreply.github.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Inbox

Development

Successfully merging this pull request may close these issues.

[Bug]: Cancelling an interrupted task leaves the robot stuck, and resuming it restarts the cancelled phase

2 participants