From a72009099ac313466c703f6b073aed98953d80b5 Mon Sep 17 00:00:00 2001 From: damocles Date: Thu, 30 Jul 2026 00:02:02 +0200 Subject: [PATCH] fix list_containers reporting stale running state handle_list_descendants derived a container's running state from membership in nixos-container list output, but that command returns every registered container - stopped and ghost-registered (machined still holds the name after the process died) ones included - not just running ones. use lifecycle::is_running (systemctl is-active on the container's systemd unit) per container instead, same source container_view::build_all already uses for the dashboard. fixes hyperhive/hyperhive#2846 --- .../src/socket_server/lifecycle_handlers.rs | 33 +++++++------------ 1 file changed, 11 insertions(+), 22 deletions(-) diff --git a/hive-c0re/src/socket_server/lifecycle_handlers.rs b/hive-c0re/src/socket_server/lifecycle_handlers.rs index 29182a69..997558e0 100644 --- a/hive-c0re/src/socket_server/lifecycle_handlers.rs +++ b/hive-c0re/src/socket_server/lifecycle_handlers.rs @@ -160,21 +160,6 @@ pub(super) fn handle_update(coord: &Arc, agent: &str, name: &str) - /// its running/stopped state, parents before children. pub(super) async fn handle_list_descendants(agent: &str) -> Response { tracing::debug!(%agent, "agent: list descendants"); - // All containers known to nixos-container (running only). - let running_set: std::collections::HashSet = match crate::lifecycle::list().await { - Ok(names) => names - .into_iter() - .filter_map(|c| { - c.strip_prefix(crate::lifecycle::AGENT_PREFIX) - .map(str::to_owned) - }) - .collect(), - Err(e) => { - return Response::Err { - message: format!("list containers failed: {e:#}"), - }; - } - }; // Walk the full topology and collect every descendant. let topo = crate::topology::read(); let mut names: Vec = topo @@ -184,12 +169,16 @@ pub(super) async fn handle_list_descendants(agent: &str) -> Response { .collect(); // Parents before children, then alpha within each tier. crate::auto_update::topology_sort(&mut names, &topo); - let containers = names - .into_iter() - .map(|name| { - let running = running_set.contains(&name); - hive_sh4re::ContainerInfo { name, running } - }) - .collect(); + // Query each container's actual systemd unit state (same source + // `container_view::build_all` uses for the dashboard). `nixos-container + // list` — what this used to key off of via a "known containers" set — + // reports every *registered* container, stopped and ghost-registered + // (machined still holds the name after a crashed/killed process) ones + // included, so membership there is not the same thing as "running". + let mut containers = Vec::with_capacity(names.len()); + for name in names { + let running = crate::lifecycle::is_running(&name).await; + containers.push(hive_sh4re::ContainerInfo { name, running }); + } Response::Containers { containers } }