From c7d478754dd8cfc77cdeb6eb58fa1ea923cfa138 Mon Sep 17 00:00:00 2001 From: Sausage Date: Mon, 2 Nov 2026 00:10:34 +0000 Subject: [PATCH] Wait for busy guest readiness before measuring shutdown grace --- cli/tests/host/core.rs | 17 +++++++++-------- cli/tests/plugins/probe/src/main.rs | 3 +++ 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/cli/tests/host/core.rs b/cli/tests/host/core.rs index 1ba0285..76bc9d1 100644 --- a/cli/tests/host/core.rs +++ b/cli/tests/host/core.rs @@ -1015,6 +1015,7 @@ async fn stop_deadlines() { async fn shutdown_stops_busy_processes_in_parallel_after_five_seconds() { let w = TestWorld::new(); let h = w.start().await; + let mut notifications = h.subscribe(); let mut tasks = Vec::new(); for _ in 0..2 { @@ -1024,14 +1025,14 @@ async fn shutdown_stops_busy_processes_in_parallel_after_five_seconds() { })); } tokio::time::timeout(std::time::Duration::from_secs(20), async { - while h - .processes() - .values() - .filter(|p| p.plugin == "probe" && p.method == "busy") - .count() - != 2 - { - tokio::task::yield_now().await; + // Admission precedes guest startup. Stopping at admission can close + // stdin before the guest receives its busy request, so there is then + // no busy work that needs the five-second kill budget. + let mut ready = 0; + while ready != tasks.len() { + if notifications.recv().await.unwrap()["params"]["name"] == "busy-ready" { + ready += 1; + } } }) .await diff --git a/cli/tests/plugins/probe/src/main.rs b/cli/tests/plugins/probe/src/main.rs index 7ba2cf9..51a38ae 100644 --- a/cli/tests/plugins/probe/src/main.rs +++ b/cli/tests/plugins/probe/src/main.rs @@ -90,6 +90,9 @@ fn wait_eof(lines: &mut Lines) { std::fs::write("/state/stopped", "yes").unwrap(); } fn busy() -> Value { + send(json!({"jsonrpc":"2.0", "method":"core.notify", "params":{ + "name":"busy-ready", "params":{} + }})); loop { std::hint::spin_loop(); }