From 0877bd970d41f7b61016cdcbbc0e8a1e949b2863 Mon Sep 17 00:00:00 2001 From: Marco Allegretti Date: Wed, 11 Mar 2026 18:20:16 +0100 Subject: [PATCH] fix(appd): kill file portal process on all early-return paths in supervise() Runtime spawn failure, READY timeout, and abort-during-startup all previously returned without killing the portal child process or removing its socket file. Extracted kill_portal() to consolidate cleanup and call it in each of those three paths. --- crates/weft-appd/src/runtime.rs | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/crates/weft-appd/src/runtime.rs b/crates/weft-appd/src/runtime.rs index 79526f1..a885993 100644 --- a/crates/weft-appd/src/runtime.rs +++ b/crates/weft-appd/src/runtime.rs @@ -87,6 +87,14 @@ fn resolve_preopens(app_id: &str) -> Vec<(String, String)> { preopens } +async fn kill_portal(portal: Option<(PathBuf, tokio::process::Child)>) { + if let Some((sock, mut child)) = portal { + let _ = child.kill().await; + let _ = child.wait().await; + let _ = std::fs::remove_file(&sock); + } +} + fn portal_socket_path(session_id: u64) -> Option { let runtime_dir = std::env::var("XDG_RUNTIME_DIR").ok()?; let dir = PathBuf::from(runtime_dir).join("weft"); @@ -181,6 +189,7 @@ pub(crate) async fn supervise( Ok(c) => c, Err(e) => { tracing::warn!(session_id, %app_id, error = %e, "failed to spawn runtime; marking session stopped"); + kill_portal(portal).await; let mut reg = registry.lock().await; reg.set_state(session_id, AppStateKind::Stopped); let _ = reg.broadcast().send(Response::AppState { @@ -229,6 +238,7 @@ pub(crate) async fn supervise( Some(Err(_elapsed)) => { tracing::warn!(session_id, %app_id, "READY timeout after 30s; killing process"); let _ = child.kill().await; + kill_portal(portal).await; let mut reg = registry.lock().await; reg.set_state(session_id, AppStateKind::Stopped); let _ = reg.broadcast().send(Response::AppState { @@ -240,6 +250,7 @@ pub(crate) async fn supervise( None => { tracing::info!(session_id, %app_id, "abort during startup; killing process"); let _ = child.kill().await; + kill_portal(portal).await; let mut reg = registry.lock().await; reg.set_state(session_id, AppStateKind::Stopped); let _ = reg.broadcast().send(Response::AppState {