Skip to content

openvmm: cancelling a VM-time stop leaves the owner running after its keepers stop #1166

Open

Description

@tangruize

Dropping a polled VmTimeKeeper::stop future before its RPC reply can leave the owner in the started state after the primary and secondary keepers have stopped. Subsequent lifecycle calls operate on contradictory state and can panic.

In vm/vmcore/src/vmtime.rs, the owner updates its state only after awaiting the Stop reply:

    pub async fn stop(&mut self) {
        assert!(self.time.is_started(), "should be running");
        let stop_time = self.req_send.call(KeeperRequest::Stop, ()).await.unwrap();
        self.time = TimeState::Stopped(stop_time.vmtime);
        self.stop_host_time = stop_time.host_time;
    }

Once the request is sent, dropping the caller's future does not withdraw the primary's operation. The primary can finish stopping its secondary keepers, set its own time to stopped and send a reply that the owner no longer receives. Retrying stop then sends another Stop to an already-stopped primary, while the owner's save and start checks still see started time.

Trigger

Start VM time, poll stop while a secondary keeper's reply is pending, then drop that future. Let the secondary Stop and Reset requests complete. The primary is stopped, but the owner's assignments after .await never execute. The normal microVM unit dispatcher does not drop stop this way; API callers can.

Proposed Fix

Keep an owner-side stopping state that retains the pending RPC result across cancellation and reconciles both the stopped time and host-clock sample when resumed.

Define whether callers must retry stop or whether later start, reset and advance finish a pending stop automatically. Synchronous save also needs defined behavior while stopping; it must not serialize a stop that has not been reconciled.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions