Skip to content

vm rm --force should skip the graceful stop like vm stop --force does #82

Description

@CMGS

Current behavior

--force means two different things on stop and rm:

  • vm stop --force maps to StopTimeoutSeconds = -1 and terminates the VMM immediately (SIGTERM → grace → SIGKILL) — see the Stop handler in cmd/vm/lifecycle.go.
  • vm rm --force only means "allowed to delete a running VM": DeleteAll calls the backend's default stopOne, which runs the graceful path with the default 30s window (hypervisor/stop.go DeleteAllhypervisor/firecracker/stop.go stopOnegracefulStop). The RM handler never applies the -1 mapping.

Why this hurts

On Firecracker the only graceful mechanism is SendCtrlAltDel, delivered through the emulated i8042 controller. A guest kernel built without CONFIG_SERIO_I8042 / CONFIG_INPUT_KEYBOARD (typical for minimal or sandbox-oriented guests) can never observe it, so every vm rm --force of a running FC VM burns the full 30s before escalating:

WRN VM ... did not shut down within 30s, escalating  func=firecracker.GracefulStop
INF deleted: ...                                     func=cmd.vm.rm

Cloud Hypervisor is mostly unaffected: its graceful stop is an ACPI power button, which minimal guests do handle.

Ecosystem convention is also that force means "now": docker rm -f kills immediately, virsh destroy is a hard power-off. Callers wanting fast teardown currently need vm stop --force <vm> && vm rm --force <vm> as a workaround (two invocations).

Proposal

Make the RM handler apply the same mapping as Stop: with --force, set StopTimeoutSeconds = -1 so the stop-before-delete goes straight to forceTerminate.

  • Default vm rm (refusing running VMs) stays unchanged.
  • Users who relied on rm --force performing a guest-graceful shutdown first can run vm stop --timeout N && vm rm; worth a changelog line since observable behavior changes.

Alternative considered: a --timeout flag on rm (like stop). Works, but leaves the --force vocabulary inconsistency in place.

Related observation (can split into its own issue)

While testing teardown inside a container whose PID 1 does not reap orphans, an escalated SIGKILL left the VMM as a zombie; the stop path's liveness check kept treating it as alive (stop before delete: timeout after 5s) and the delete could never complete. Treating state-Z processes as dead in the liveness check would make teardown robust to non-reaping supervisors. (Environment workaround: run with an init that reaps, e.g. docker run --init.)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions