feat(minvmd): add run, status, and stop subcommands - #351
Conversation
Implements R4.2, R4.3, and R4.4 from the minvmd host daemon spec: - `minvmd run`: foreground lifecycle supervisor with StartingGuard RAII rollback; `--detach` spawns background supervisor and polls host UDS until accepting connections (configurable timeout, default 8s). - `minvmd status`: reads state.toml, prints human-readable or JSON output (fields: state, vmm_pid, uptime_seconds, vcpus, ram_mib); exit 0 if running, 1 if stopped, 2 on lifecycle lock contention. - `minvmd stop`: sends SIGTERM to vmm child, waits 5s, escalates to SIGKILL; removes vmm.pid and resets state.toml to Stopped; idempotent. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (1)
🚧 Files skipped from review as they are similar to previous changes (1)
📝 WalkthroughWalkthroughAdds three minvmd CLI subcommands: run (foreground supervisor and detached startup with UDS readiness polling), status (state query with lock-contention detection and optional JSON), and stop (graceful shutdown with SIGTERM/SIGKILL escalation). Also wires CLI dispatch and adds a workspace ChangesVM Lifecycle Management
Sequence Diagram(s)sequenceDiagram
participant User
participant CLI as minvmd_cli
participant Supervisor as minvmd_run_parent
participant Child as minvmd_run_child
participant VMM as __krun-vmm
participant HostUDS as Host_UDS
User->>CLI: minvmd run --detach
CLI->>Supervisor: spawn re-exec (setsid pre_exec)
Supervisor->>Child: detach and supervise
Child->>VMM: spawn __krun-vmm with READY socket env
VMM->>HostUDS: emit READY marker
Supervisor->>HostUDS: poll_uds_ready -> connect
Supervisor-->>User: return success
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes Possibly related issues
Possibly related PRs
Suggested labels
Suggested reviewers
Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
Comment |
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@crates/minvmd/src/cmd/status.rs`:
- Around line 51-53: The local variable rw declared as "let mut rw =
state_dir.lifecycle_lock()..." is never mutated; change it to immutable by
removing "mut" (use "let rw = state_dir.lifecycle_lock()...") so the subsequent
call rw.try_read() compiles without an unnecessary mutable binding; update the
declaration near the status logic that calls lifecycle_lock() and try_read().
In `@crates/minvmd/src/cmd/stop.rs`:
- Around line 71-77: The vmm_pid value must be range-checked before casting in
signal_and_wait so it cannot wrap into a negative PID; update signal_and_wait
(where you do let pid_t = pid as libc::pid_t) to perform a checked conversion
from u32 to libc::pid_t (e.g., using TryInto or comparing against
libc::pid_t::MAX) and return an Err (or a clear error) when vmm_pid is None or
exceeds the pid_t max, rather than blindly casting; ensure callers that read
state.vmm_pid (from state.rs) handle this error path so you never call
libc::kill with a wrapped/negative pid.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 958c7a66-409d-4989-ad7f-4a2591f68e56
📒 Files selected for processing (6)
crates/minvmd/Cargo.tomlcrates/minvmd/src/cmd/mod.rscrates/minvmd/src/cmd/run.rscrates/minvmd/src/cmd/status.rscrates/minvmd/src/cmd/stop.rscrates/minvmd/src/main.rs
This comment has been minimized.
This comment has been minimized.
|
/revise fix the ci failure Validate the coderabiit issue and fix them if they are valid |
There was a problem hiding this comment.
Generated by sdd-review for issue #351 · ● 41.2M
- status.rs: remove mut from let mut rw (Clippy unused-mut) - stop.rs: replace pid as libc::pid_t with checked try_from to prevent silent wrapping when vmm_pid > i32::MAX; reject pid <= 0 to avoid signaling the wrong process group - Add tests for both new error paths Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
|
Commit pushed:
|
This comment has been minimized.
This comment has been minimized.
There was a problem hiding this comment.
Generated by sdd-review for issue #351 · ● 34.9M
The macOS-gated run_detach and run_foreground functions call .context() and .with_context() on Result values, which require anyhow::Context to be in scope. The trait was missing, which would cause a compile error on macOS (not caught on Linux CI because the callers are cfg-gated). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
|
Commit pushed:
|
This comment has been minimized.
This comment has been minimized.
There was a problem hiding this comment.
Generated by sdd-review for issue #351 · ● 29.9M
The `.context()`/`.with_context()` calls in run.rs live entirely in the macOS-gated supervisor functions; the Linux build is a no-op stub. The unconditional `use anyhow::Context as _;` was therefore unused on Linux, failing `cargo clippy --all-targets -- -D warnings` (unused-imports) in the Linux CI job while compiling cleanly on macOS. Scope the trait import to `#[cfg(target_os = "macos")]` so it is present exactly where it is used. `Result` and `bail` stay unconditional — both are used by the Linux stub and poll_uds_ready. Refs: #330
sdd-validate · Implementation boundary · PR #351Boundary: Implementation — all changed files are Rust source, build configuration, or lockfile; no spec, architecture, or decisions files. Task: #330 (Run, status, and stop subcommands) · requirements R4.2, R4.3, R4.4 Findings1. Proof artifacts re-executed and passing
2. Changed files within task scope
3. No real credentials in the diff
Result: Implementation boundary passed clean (no Blocker findings). 1 Warning, 2 Info. Lifecycle: Feature #311 already carries
|
There was a problem hiding this comment.
Generated by sdd-review for issue #351 · ● 26M
Implements R4.2, R4.3, and R4.4 from the minvmd host daemon spec.
Closes #330
Changes
minvmd run(R4.2)Stopped → Starting → Running → Stopped) via brief write locks onlifecycle.lockStartingGuardRAII rollback resets toStoppedif boot fails before the VMM child signalsREADY--detach: spawns a detached supervisor (setsid) and polls the host UDS until accepting connections; configurable--timeout(default 8 s)minvmd status(R4.3)state.toml; prints human-readable (default) or JSON (--json) outputstate,vmm_pid,uptime_seconds,vcpus,ram_mibtry_read()onlifecycle.lock)minvmd stop(R4.4)vmm_pidfrom state under write lock, then releases lock before signalingSIGTERM; polls process existence every 100 ms for up to 5 s; escalates toSIGKILLon timeoutvmm.pidand writesStoppedstate under lockStopped,NotProvisioned, andStoppingstates all returnOk(())immediatelyProof artifacts
Test — unit tests for
poll_uds_ready,StatusExitexit codes, stop idempotency and cleanup:Tests that must pass (and fail before this PR):
cmd::run::tests::poll_uds_returns_ok_when_listener_is_readycmd::run::tests::poll_uds_times_out_when_no_listenercmd::run::tests::run_bails_on_non_macos(Linux CI only)cmd::status::tests::not_provisioned_exits_stoppedcmd::status::tests::stopped_state_exits_stoppedcmd::status::tests::running_state_exits_runningcmd::status::tests::starting_state_exits_stoppedcmd::status::tests::json_output_contains_required_fieldscmd::status::tests::lock_contention_exits_2cmd::stop::tests::stop_is_noop_when_not_provisionedcmd::stop::tests::stop_is_noop_when_already_stoppedcmd::stop::tests::stop_is_noop_when_already_stoppingcmd::stop::tests::stop_cleans_up_running_state_with_nonexistent_pidcmd::stop::tests::stop_with_no_pid_in_state_still_resets_to_stoppedCLI — stop is idempotent and exits 1 on a stopped daemon:
Warning
Firewall blocked 1 domain
The following domain was blocked by the firewall during workflow execution:
index.crates.ioSee Network Configuration for more information.
Summary by CodeRabbit
New Features
minvmd runto start the VM supervisor in foreground or detached background with a configurable timeout (and a default).minvmd statusto report daemon state and uptime (human or--json) and return distinct exit codes for running/stopped/lock contention.minvmd stopto gracefully stop the VM supervisor, signal the VMM, and clean up persisted state.Tests