Canceling an OTA Update: State the Last Point Where Cancellation Is Safe

For a wrapper using RAUC 1.14’s documented D-Bus interface, promise cancellation only before the installation request is dispatched, after all application-owned work has acknowledged that it stopped. Once dispatch may have occurred, report a stop request or an unresolved result rather than claiming the installation was canceled.

This is a deliberately conservative contract for one pinned interface. It does not assert that every installer lacks cancellation or that every update stage is physically irreversible. A different product may expose a qualified abort operation, but its exact guarantees must establish the boundary. No installer, flash operation or process interruption was executed here.

1. Name the operation the button controls

A cancel button might mean remove a queued job, stop an application-owned download, prevent installation, prevent a later reboot, or recover from an installed release. Those outcomes are different. Write the promised effect beside the button before implementing its handler.

For this example, “Cancel update” means prevent dispatch of the selected installation request. It may also stop preparation owned by the wrapper, but only after that worker acknowledges completion. It does not promise to undo firmware writes, restore application data, or reverse a boot-selection change.

If the product supports a separate reboot hold, expose it as a separate action with its own authority and verification. Do not assume a still-running old application means the installation has had no persistent effect.

A single state owner arbitrates cancel against dispatch; only a pre-dispatch win with worker acknowledgement yields canceled, while dispatched or uncertain requests retain actual installer outcomes.
Original cancellation contract for a RAUC 1.14 D-Bus wrapper. The figure does not imply a supported mid-flash abort method.

2. Pin the installer boundary to the actual API

The RAUC 1.14 reference describes InstallBundle as nonblocking, with a later Completed signal. The complete v1.14 installer interface contains no Cancel method. Therefore this wrapper must not invent an acknowledged mid-install cancellation primitive from closing its D-Bus connection or abandoning a method wait.

A timeout describes the client’s observation, not necessarily the daemon’s execution state. If a request was sent and its reply was lost, acceptance is uncertain. Keep that outcome unresolved until the supported status and completion paths establish what happened.

Do not terminate the installer process, remove storage or cut power to simulate a supported cancel action. Those are fault or recovery operations requiring separate qualification and authority. They are not interchangeable with an API that guarantees a safe abort.

3. Serialize cancel with dispatch

Use one application state owner to decide the race between cancellation and dispatch. A proposed state sequence is PREPARING, READY, DISPATCHING, INSTALLING and terminal outcome. A cancellation request can win only before the transition to DISPATCHING has been committed by that owner.

When cancel wins, record that the request will never be dispatched, stop application-owned producers through their supported mechanisms, and wait for acknowledgement that no callback can dispatch it later. Only then return CANCELED-BEFORE-DISPATCH. An earlier optimistic UI message such as “canceling” must not be stored as a final result.

When dispatch wins, record that cancellation arrived too late for this contract. Continue observing the installer. A local sequence number or timestamp can document the decision, but the user’s click time alone cannot settle a race occurring in another process.

Include persistence around this boundary. A restart after recording DISPATCHING but before receiving a method reply must recover as possibly dispatched. Do not replay a queued cancel and conclude that the original request never reached the daemon.

4. Give each stage a truthful response

Observed stage Permitted wrapper response Evidence needed
Queued, not started Cancel the queued intent It cannot later be selected for dispatch
Application-owned preparation Request stop, then confirm cancellation Worker acknowledgement and closed dispatch path
Ready, before dispatch decision Arbitrate cancel versus dispatch One recorded winner
Request possibly dispatched Report acceptance unresolved Reconciliation, not a timeout assumption
Installer accepted the request Report cancellation unavailable through this interface Actual installer completion remains pending
Installation completed Show the real result and later boot status Completion evidence plus separate activation policy

The same table should drive logs, service responses and the UI. A background operation must not finish successfully while its only retained record says “canceled.” Conversely, canceling an unsent job should not be counted as an installation failure.

5. Preserve stage-specific terminal outcomes

Use distinct results for canceled before dispatch, cancellation requested but unavailable, installation completed after a stop request, installation failed after a stop request, and outcome unresolved. Keep both the requested action and observed result. They answer different support questions.

The RAUC boot-confirmation guidance also separates installation from successful subsequent operation. Thus, completed installation after a late cancel request is not proof that the new system has booted, passed health checks or been confirmed.

Retain the artifact and operation identifiers, dispatch decision, cancellation acknowledgement if any, and completion evidence. Exclude access tokens and private image contents. If a later authorized recovery is required, create a separate recovery record rather than rewriting the historical installation as if it never occurred.

6. Test the boundary rather than only the button

  1. Cancel a queued job and later restart the queue owner.
  2. Cancel preparation while its last completion callback is pending.
  3. Race cancel with the single dispatch transition in both orders.
  4. Lose the method reply after the request could have reached RAUC.
  5. Restart the wrapper with a persisted DISPATCHING record.
  6. Receive successful or failed completion after the user requested cancellation.

First exercise a synthetic dispatcher that records calls without installing anything. The key invariant is zero dispatches for every final CANCELED-BEFORE-DISPATCH result. Then qualify actual daemon behavior on a recoverable test device, preserving user data and using the product’s approved fault procedures. These tests are proposed and were not executed for this article.

Hypothetical late click

A technician clicks cancel just after the wrapper has committed dispatch. The UI changes to “Stop requested; installation outcome pending,” rather than showing a completed cancellation. RAUC subsequently reports installation success, so the record says it completed after the request and presents the separate reboot or health state.

If the click had won before dispatch, the wrapper would have prevented the call and waited for preparation to stop before confirming cancellation. That precise boundary gives the operator a promise the implementation can actually keep.

Similar Posts