From 4b3c66af3c106b9c0673de8c34a8bd4c1ef2867f Mon Sep 17 00:00:00 2001 From: Valentin Haudiquet Date: Fri, 30 Oct 2026 23:13:03 +0100 Subject: [PATCH] docs(vm): state the machine child's fork constraint The fork contract lived in a comment inside run_prepared; an embedder meeting it first in the public API docs, with the fork-with-threads hazard spelled out, has a chance of honoring it. --- crates/ecrou/src/vm.rs | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/crates/ecrou/src/vm.rs b/crates/ecrou/src/vm.rs index b140490..f225205 100644 --- a/crates/ecrou/src/vm.rs +++ b/crates/ecrou/src/vm.rs @@ -102,6 +102,14 @@ impl Default for RunOptions { } /// Run one machine to completion and return the payload's exit code. +/// +/// The machine is a forked child of this process, and the child never +/// execs: it configures libkrun in the same process image and enters +/// the VMM there. ecrou's own work (downloads, image builds) is done +/// before the fork; a consumer running other threads alongside `run` +/// should know the fork lands in their thread state, and a thread +/// holding the allocator or dynamic-loader lock at that instant can +/// deadlock the machine child. pub fn run(options: &RunOptions, progress: &dyn Progress) -> Result { let mut request = PrepareRequest::new(options.image.clone()); request.arch = options.arch.clone(); @@ -114,7 +122,9 @@ pub fn run(options: &RunOptions, progress: &dyn Progress) -> Result { } /// Boot one machine over an already-prepared rootfs. This is the -/// boot half of [`run`]: prepare lands the tree, this boots it. +/// boot half of [`run`]: prepare lands the tree, this boots it. The +/// machine is a forked child that never execs; see [`run`] for the +/// threading constraint that carries. pub fn run_prepared(rootfs: &PreparedRootfs, options: &RunOptions) -> Result { if options.image.is_empty() { return Err(Error::Other(anyhow!("no image given")));