修复agent执行命令可能会残留子进程
This commit is contained in:
1
src-tauri/Cargo.lock
generated
1
src-tauri/Cargo.lock
generated
@@ -4730,6 +4730,7 @@ name = "sacp-tokio"
|
|||||||
version = "11.0.0-alpha.1"
|
version = "11.0.0-alpha.1"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"futures",
|
"futures",
|
||||||
|
"kill_tree",
|
||||||
"sacp",
|
"sacp",
|
||||||
"serde",
|
"serde",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
|
|||||||
@@ -47,6 +47,7 @@ toml = "0.8"
|
|||||||
notify = "6"
|
notify = "6"
|
||||||
base64 = "0.22"
|
base64 = "0.22"
|
||||||
agent-client-protocol-schema = { version = "0.10", features = ["unstable_session_usage"] }
|
agent-client-protocol-schema = { version = "0.10", features = ["unstable_session_usage"] }
|
||||||
|
kill_tree = { version = "0.2", features = ["tokio"] }
|
||||||
|
|
||||||
[target.'cfg(not(any(target_os = "android", target_os = "ios")))'.dependencies]
|
[target.'cfg(not(any(target_os = "android", target_os = "ios")))'.dependencies]
|
||||||
tauri-plugin-window-state = "2"
|
tauri-plugin-window-state = "2"
|
||||||
@@ -56,7 +57,6 @@ tauri-plugin-process = "2"
|
|||||||
|
|
||||||
[target.'cfg(target_os = "windows")'.dependencies]
|
[target.'cfg(target_os = "windows")'.dependencies]
|
||||||
windows-sys = { version = "0.59", features = ["Win32_Storage_FileSystem"] }
|
windows-sys = { version = "0.59", features = ["Win32_Storage_FileSystem"] }
|
||||||
kill_tree = { version = "0.2", features = ["tokio"] }
|
|
||||||
|
|
||||||
[patch.crates-io]
|
[patch.crates-io]
|
||||||
sacp-tokio = { path = "vendor/sacp-tokio" }
|
sacp-tokio = { path = "vendor/sacp-tokio" }
|
||||||
|
|||||||
@@ -190,6 +190,22 @@ impl ConnectionManager {
|
|||||||
disconnected
|
disconnected
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub async fn disconnect_all(&self) -> usize {
|
||||||
|
let cmd_txs: Vec<_> = {
|
||||||
|
let mut connections = self.connections.lock().await;
|
||||||
|
connections
|
||||||
|
.drain()
|
||||||
|
.map(|(_, conn)| conn.cmd_tx)
|
||||||
|
.collect()
|
||||||
|
};
|
||||||
|
let disconnected = cmd_txs.len();
|
||||||
|
for cmd_tx in cmd_txs {
|
||||||
|
let _ = cmd_tx.send(ConnectionCommand::Disconnect).await;
|
||||||
|
}
|
||||||
|
eprintln!("[ACP] disconnect_all count={}", disconnected);
|
||||||
|
disconnected
|
||||||
|
}
|
||||||
|
|
||||||
pub async fn list_connections(&self) -> Vec<ConnectionInfo> {
|
pub async fn list_connections(&self) -> Vec<ConnectionInfo> {
|
||||||
let connections = self.connections.lock().await;
|
let connections = self.connections.lock().await;
|
||||||
connections.values().map(|c| c.info()).collect()
|
connections.values().map(|c| c.info()).collect()
|
||||||
|
|||||||
@@ -149,21 +149,9 @@ impl TerminalInstance {
|
|||||||
return Ok(());
|
return Ok(());
|
||||||
};
|
};
|
||||||
|
|
||||||
#[cfg(target_os = "windows")]
|
if let Some(pid) = child.id() {
|
||||||
{
|
if let Err(err) = kill_tree::tokio::kill_tree(pid).await {
|
||||||
if let Some(pid) = child.id() {
|
eprintln!("[ACP] kill_tree failed for pid {pid}: {err}");
|
||||||
let _ = kill_tree::tokio::kill_tree(pid);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(not(target_os = "windows"))]
|
|
||||||
{
|
|
||||||
if let Err(err) = child.kill().await {
|
|
||||||
if err.kind() != std::io::ErrorKind::InvalidInput {
|
|
||||||
return Err(TerminalRuntimeError::Internal(format!(
|
|
||||||
"failed to kill terminal process: {err}"
|
|
||||||
)));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -268,9 +268,17 @@ pub fn run() {
|
|||||||
])
|
])
|
||||||
.build(tauri::generate_context!())
|
.build(tauri::generate_context!())
|
||||||
.expect("error while building tauri application")
|
.expect("error while building tauri application")
|
||||||
.run(|_app, event| {
|
.run(|app, event| {
|
||||||
if let tauri::RunEvent::ExitRequested { .. } = event {
|
if let tauri::RunEvent::ExitRequested { .. } = event {
|
||||||
APP_QUITTING.store(true, Ordering::Relaxed);
|
APP_QUITTING.store(true, Ordering::Relaxed);
|
||||||
|
// Kill all terminal sessions to prevent orphaned processes.
|
||||||
|
if let Some(tm) = app.try_state::<TerminalManager>() {
|
||||||
|
tm.kill_all();
|
||||||
|
}
|
||||||
|
// Disconnect all ACP agent connections (kills agent process trees).
|
||||||
|
if let Some(cm) = app.try_state::<ConnectionManager>() {
|
||||||
|
tauri::async_runtime::block_on(cm.disconnect_all());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -328,6 +328,19 @@ impl TerminalManager {
|
|||||||
}
|
}
|
||||||
killed
|
killed
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn kill_all(&self) -> usize {
|
||||||
|
let mut instances: Vec<TerminalInstance> = {
|
||||||
|
let mut terminals = self.terminals.lock().unwrap();
|
||||||
|
terminals.drain().map(|(_, inst)| inst).collect()
|
||||||
|
};
|
||||||
|
let killed = instances.len();
|
||||||
|
for instance in &mut instances {
|
||||||
|
terminate_terminal(instance);
|
||||||
|
}
|
||||||
|
eprintln!("[TERM] kill_all killed_terminals={}", killed);
|
||||||
|
killed
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn terminate_terminal(instance: &mut TerminalInstance) {
|
fn terminate_terminal(instance: &mut TerminalInstance) {
|
||||||
|
|||||||
3
src-tauri/vendor/sacp-tokio/Cargo.toml
vendored
3
src-tauri/vendor/sacp-tokio/Cargo.toml
vendored
@@ -61,6 +61,9 @@ version = "1.1"
|
|||||||
version = "1.48"
|
version = "1.48"
|
||||||
features = ["full"]
|
features = ["full"]
|
||||||
|
|
||||||
|
[dependencies.kill_tree]
|
||||||
|
version = "0.2"
|
||||||
|
|
||||||
[dependencies.tokio-util]
|
[dependencies.tokio-util]
|
||||||
version = "0.7"
|
version = "0.7"
|
||||||
features = ["compat"]
|
features = ["compat"]
|
||||||
|
|||||||
6
src-tauri/vendor/sacp-tokio/src/acp_agent.rs
vendored
6
src-tauri/vendor/sacp-tokio/src/acp_agent.rs
vendored
@@ -230,7 +230,11 @@ impl ChildGuard {
|
|||||||
|
|
||||||
impl Drop for ChildGuard {
|
impl Drop for ChildGuard {
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
let _ = self.0.start_kill();
|
if let Some(pid) = self.0.id() {
|
||||||
|
let _ = kill_tree::blocking::kill_tree(pid);
|
||||||
|
} else {
|
||||||
|
let _ = self.0.start_kill();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user