diff --git a/hive-c0re/src/lifecycle.rs b/hive-c0re/src/lifecycle.rs index abbc94a7..8b5b056b 100644 --- a/hive-c0re/src/lifecycle.rs +++ b/hive-c0re/src/lifecycle.rs @@ -444,17 +444,26 @@ pub async fn rebuild_no_meta( // the old-generation activation references units that no longer // exist in the new closure, causing systemd to exit non-zero. // - // Fallback: kill + start (cold-start). `kill` SIGKILLs any - // lingering container processes so the next `start` enters a - // clean state without a generation transition, letting the - // activation succeed. + // Fallback: stop + kill + start (cold-start). The activation + // script can fail when packages are removed between generations — + // `start` exits non-zero but the container may be half-started. + // `stop` requests a graceful SIGTERM drain; `kill` then SIGKILLs + // any lingering processes so the next `start` enters a clean state + // without a generation transition, letting the activation succeed. if let Err(start_err) = run(&["start", &container]).await { tracing::warn!( container = %container, error = %start_err, "start after rebuild failed (possible activation error); \ - retrying via kill + start" + retrying via stop + kill + start" ); + run(&["stop", &container]).await.unwrap_or_else(|e| { + tracing::warn!( + container = %container, + error = %e, + "stop before cold-start retry failed (ignored)" + ); + }); run(&["kill", &container]).await.unwrap_or_else(|e| { tracing::warn!( container = %container,