nu_system/
util.rs

1use std::io;
2use std::process::Command as CommandSys;
3
4/// Tries to forcefully kill a process by its PID
5pub fn kill_by_pid(pid: i64) -> Result<(), KillByPidError> {
6    let mut cmd = build_kill_command(true, std::iter::once(pid), None);
7
8    let output = cmd.output().map_err(KillByPidError::Output)?;
9
10    match output.status.success() {
11        true => Ok(()),
12        false => Err(KillByPidError::KillProcess),
13    }
14}
15
16/// Error while killing a process forcefully by its PID.
17pub enum KillByPidError {
18    /// I/O error while capturing the output of the process.
19    Output(io::Error),
20
21    /// Killing the process failed.
22    KillProcess,
23}
24
25/// Create a `std::process::Command` for the current target platform, for killing
26/// the processes with the given PIDs
27pub fn build_kill_command(
28    force: bool,
29    pids: impl Iterator<Item = i64>,
30    signal: Option<u32>,
31) -> CommandSys {
32    if cfg!(windows) {
33        let mut cmd = CommandSys::new("taskkill");
34
35        if force {
36            cmd.arg("/F");
37        }
38
39        // each pid must written as `/PID 0` otherwise
40        // taskkill will act as `killall` unix command
41        for id in pids {
42            cmd.arg("/PID");
43            cmd.arg(id.to_string());
44        }
45
46        cmd
47    } else {
48        let mut cmd = CommandSys::new("kill");
49        if let Some(signal_value) = signal {
50            cmd.arg(format!("-{signal_value}"));
51        } else if force {
52            cmd.arg("-9");
53        }
54
55        cmd.args(pids.map(move |id| id.to_string()));
56
57        cmd
58    }
59}