use std::process::Stdio;
use std::time::Duration;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Grace {
Immediate,
Graceful,
}
const GRACE_PERIOD: Duration = Duration::from_millis(400);
pub async fn terminate_tree(pid: u32, grace: Grace) {
#[cfg(not(target_os = "windows"))]
{
if grace == Grace::Graceful {
unix_kill("-TERM", pid).await;
tokio::time::sleep(GRACE_PERIOD).await;
}
unix_kill("-KILL", pid).await;
}
#[cfg(target_os = "windows")]
{
let _ = grace; taskkill_tree(pid).await;
}
}
pub fn terminate_tree_blocking(pid: u32, grace: Grace) {
#[cfg(not(target_os = "windows"))]
{
if grace == Grace::Graceful {
unix_kill_blocking("-TERM", pid);
std::thread::sleep(GRACE_PERIOD);
}
unix_kill_blocking("-KILL", pid);
}
#[cfg(target_os = "windows")]
{
let _ = grace;
taskkill_tree_blocking(pid);
}
}
#[cfg(not(target_os = "windows"))]
async fn unix_kill(signal: &str, pid: u32) {
let _ = tokio::process::Command::new("kill")
.args([signal, "--", &format!("-{pid}"), &pid.to_string()])
.stdin(Stdio::null())
.stdout(Stdio::null())
.stderr(Stdio::null())
.status()
.await;
}
#[cfg(not(target_os = "windows"))]
fn unix_kill_blocking(signal: &str, pid: u32) {
let _ = std::process::Command::new("kill")
.args([signal, "--", &format!("-{pid}"), &pid.to_string()])
.stdin(Stdio::null())
.stdout(Stdio::null())
.stderr(Stdio::null())
.status();
}
#[cfg(target_os = "windows")]
async fn taskkill_tree(pid: u32) {
let _ = tokio::process::Command::new("taskkill")
.args(["/PID", &pid.to_string(), "/T", "/F"])
.stdin(Stdio::null())
.stdout(Stdio::null())
.stderr(Stdio::null())
.status()
.await;
}
#[cfg(target_os = "windows")]
fn taskkill_tree_blocking(pid: u32) {
let _ = std::process::Command::new("taskkill")
.args(["/PID", &pid.to_string(), "/T", "/F"])
.stdin(Stdio::null())
.stdout(Stdio::null())
.stderr(Stdio::null())
.status();
}