From 6c20a99d582b1526cb37e800edbae59452d148a6 Mon Sep 17 00:00:00 2001 From: Miguel Palhas Date: Fri, 4 Sep 2026 22:03:23 +0100 Subject: [PATCH] feat(maestro): end adapter children on daemon shutdown (#134) SIGTERM now counts as a shutdown alongside ctrl-c: systemd stops the unit with SIGTERM, and with KillMode=process nothing else would reach the claude-code-acp children. After the listener drains the manager terminates every adapter before the process exits. --- crates/maestro-daemon/src/cli.rs | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/crates/maestro-daemon/src/cli.rs b/crates/maestro-daemon/src/cli.rs index 47b5dc3..fd45d42 100644 --- a/crates/maestro-daemon/src/cli.rs +++ b/crates/maestro-daemon/src/cli.rs @@ -106,7 +106,7 @@ async fn run(config_override: Option) -> Result<(), Box> { projects.start_background_refresh(); let router = local_api::router(local_api::state_for( - manager, + manager.clone(), config.hostname.clone(), config.home_dir.clone(), config.spawn_presets.clone(), @@ -118,14 +118,25 @@ async fn run(config_override: Option) -> Result<(), Box> { let bound = listener.local_addr()?; tracing::info!(addr = %bound, "API listening"); + // Ctrl-C at a terminal or SIGTERM from systemd: either one is a + // shutdown, and both must reach the adapter children below (#134). The + // unit's `KillMode=process` signals only the daemon, so nothing else + // would end them. let shutdown = async { - let _ = tokio::signal::ctrl_c().await; - tracing::info!("ctrl-c received — shutting down"); + let mut sigterm = tokio::signal::unix::signal(tokio::signal::unix::SignalKind::terminate()) + .expect("install SIGTERM handler"); + tokio::select! { + _ = tokio::signal::ctrl_c() => tracing::info!("ctrl-c received — shutting down"), + _ = sigterm.recv() => tracing::info!("SIGTERM received — shutting down"), + } }; axum::serve(listener, router) .tcp_nodelay(true) .with_graceful_shutdown(shutdown) .await?; + // tmux sessions outlive the daemon by design; structured sessions' + // adapter children do not (#134). + manager.shutdown().await; Ok(()) }