修复agent执行命令可能会残留子进程
This commit is contained in:
@@ -190,6 +190,22 @@ impl ConnectionManager {
|
||||
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> {
|
||||
let connections = self.connections.lock().await;
|
||||
connections.values().map(|c| c.info()).collect()
|
||||
|
||||
@@ -149,21 +149,9 @@ impl TerminalInstance {
|
||||
return Ok(());
|
||||
};
|
||||
|
||||
#[cfg(target_os = "windows")]
|
||||
{
|
||||
if let Some(pid) = child.id() {
|
||||
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}"
|
||||
)));
|
||||
}
|
||||
if let Some(pid) = child.id() {
|
||||
if let Err(err) = kill_tree::tokio::kill_tree(pid).await {
|
||||
eprintln!("[ACP] kill_tree failed for pid {pid}: {err}");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -268,9 +268,17 @@ pub fn run() {
|
||||
])
|
||||
.build(tauri::generate_context!())
|
||||
.expect("error while building tauri application")
|
||||
.run(|_app, event| {
|
||||
.run(|app, event| {
|
||||
if let tauri::RunEvent::ExitRequested { .. } = event {
|
||||
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
|
||||
}
|
||||
|
||||
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) {
|
||||
|
||||
Reference in New Issue
Block a user