aft/bash_background/
process.rs1use std::process::Child;
8#[cfg(windows)]
9use std::process::{Command, Stdio};
10use std::thread;
11use std::time::{Duration, Instant};
12
13pub const TERMINATE_GRACE: Duration = Duration::from_secs(2);
14
15#[cfg(unix)]
16pub fn terminate_process(child: &mut Child) {
17 let pgid = child.id() as i32;
18 terminate_pgid(pgid, Some(child));
19}
20
21#[cfg(unix)]
22pub fn terminate_pgid(pgid: i32, mut child: Option<&mut Child>) {
23 unsafe {
24 libc::killpg(pgid, libc::SIGTERM);
25 }
26 let grace_started = Instant::now();
27 while grace_started.elapsed() < TERMINATE_GRACE {
28 if let Some(child) = child.as_deref_mut() {
29 if matches!(child.try_wait(), Ok(Some(_))) {
30 return;
31 }
32 }
33 thread::sleep(Duration::from_millis(50));
34 }
35 unsafe {
36 libc::killpg(pgid, libc::SIGKILL);
37 }
38}
39
40#[cfg(windows)]
41pub fn terminate_process(child: &mut Child) {
42 let pid = child.id().to_string();
43 let _ = Command::new("taskkill")
44 .args(["/PID", &pid, "/T", "/F"])
45 .stdout(Stdio::null())
46 .stderr(Stdio::null())
47 .status();
48}