diff --git a/crates/agent_servers/src/acp.rs b/crates/agent_servers/src/acp.rs index 0664b437505155beada380484bba4409b0a87695..97bc172a41157a6e9434b34bb20b7225e9eb0821 100644 --- a/crates/agent_servers/src/acp.rs +++ b/crates/agent_servers/src/acp.rs @@ -9,7 +9,7 @@ use futures::io::BufReader; use project::Project; use project::agent_server_store::AgentServerCommand; use serde::Deserialize; -use util::ResultExt; +use util::ResultExt as _; use std::path::PathBuf; use std::{any::Any, cell::RefCell}; @@ -33,6 +33,9 @@ pub struct AcpConnection { agent_capabilities: acp::AgentCapabilities, default_mode: Option, root_dir: PathBuf, + // NB: Don't move this into the wait_task, since we need to ensure the process is + // killed on drop (setting kill_on_drop on the command seems to not always work). + child: smol::process::Child, _io_task: Task>, _wait_task: Task>, _stderr_task: Task>, @@ -81,8 +84,7 @@ impl AcpConnection { .envs(command.env.iter().flatten()) .stdin(std::process::Stdio::piped()) .stdout(std::process::Stdio::piped()) - .stderr(std::process::Stdio::piped()) - .kill_on_drop(true); + .stderr(std::process::Stdio::piped()); if !is_remote { child.current_dir(root_dir); } @@ -122,8 +124,9 @@ impl AcpConnection { let wait_task = cx.spawn({ let sessions = sessions.clone(); + let status_fut = child.status(); async move |cx| { - let status = child.status().await?; + let status = status_fut.await?; for session in sessions.borrow().values() { session @@ -174,6 +177,7 @@ impl AcpConnection { _io_task: io_task, _wait_task: wait_task, _stderr_task: stderr_task, + child, }) } @@ -186,6 +190,13 @@ impl AcpConnection { } } +impl Drop for AcpConnection { + fn drop(&mut self) { + // See the comment on the child field. + self.child.kill().log_err(); + } +} + impl AgentConnection for AcpConnection { fn new_thread( self: Rc,