KillOnDrop: SIGTERM process group when tool task is aborted
tokio::spawn abort drops the future but leaves child processes running as orphans. KillOnDrop sends SIGTERM to the process group on drop, ensuring cleanup. Defused via mem::forget on normal completion. Co-Developed-By: Kent Overstreet <kent.overstreet@linux.dev>
This commit is contained in:
parent
a78f310e4d
commit
310bbe9fce
1 changed files with 15 additions and 0 deletions
|
|
@ -14,6 +14,18 @@ use tokio::io::AsyncReadExt;
|
|||
|
||||
use super::{ToolDef, ProcessTracker, default_timeout};
|
||||
|
||||
/// RAII guard that SIGTERMs the process group on drop.
|
||||
/// Ensures child processes are cleaned up when a task is aborted.
|
||||
struct KillOnDrop(u32); // pid
|
||||
|
||||
impl Drop for KillOnDrop {
|
||||
fn drop(&mut self) {
|
||||
if self.0 != 0 {
|
||||
unsafe { libc::kill(-(self.0 as i32), libc::SIGTERM); }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
struct Args {
|
||||
command: String,
|
||||
|
|
@ -60,6 +72,7 @@ pub async fn run_bash(args: &serde_json::Value, tracker: &ProcessTracker) -> Res
|
|||
.with_context(|| format!("Failed to spawn: {}", command))?;
|
||||
|
||||
let pid = child.id().unwrap_or(0);
|
||||
let kill_guard = KillOnDrop(pid);
|
||||
tracker.register(pid, command).await;
|
||||
|
||||
// Take ownership of stdout/stderr handles before waiting,
|
||||
|
|
@ -132,6 +145,8 @@ pub async fn run_bash(args: &serde_json::Value, tracker: &ProcessTracker) -> Res
|
|||
}
|
||||
};
|
||||
|
||||
// Process completed normally — defuse the kill guard
|
||||
std::mem::forget(kill_guard);
|
||||
tracker.unregister(pid).await;
|
||||
result
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue