solana_install/
stop_process.rs1use std::{io, process::Child};
2
3fn kill_process(process: &mut Child) -> Result<(), io::Error> {
4 if let Ok(()) = process.kill() {
5 process.wait()?;
6 } else {
7 println!("Process {} has already exited", process.id());
8 }
9 Ok(())
10}
11
12#[cfg(windows)]
13pub fn stop_process(process: &mut Child) -> Result<(), io::Error> {
14 kill_process(process)
15}
16
17#[cfg(not(windows))]
18pub fn stop_process(process: &mut Child) -> Result<(), io::Error> {
19 use {
20 nix::{
21 errno::Errno::{EINVAL, EPERM, ESRCH},
22 sys::signal::{kill, Signal},
23 unistd::Pid,
24 },
25 std::{
26 io::ErrorKind,
27 thread,
28 time::{Duration, Instant},
29 },
30 };
31
32 let nice_wait = Duration::from_secs(5);
33 let pid = Pid::from_raw(process.id() as i32);
34 match kill(pid, Signal::SIGINT) {
35 Ok(()) => {
36 let expire = Instant::now() + nice_wait;
37 while let Ok(None) = process.try_wait() {
38 if Instant::now() > expire {
39 break;
40 }
41 thread::sleep(nice_wait / 10);
42 }
43 if let Ok(None) = process.try_wait() {
44 kill_process(process)?;
45 }
46 }
47 Err(EINVAL) => {
48 println!("Invalid signal. Killing process {pid}");
49 kill_process(process)?;
50 }
51 Err(EPERM) => {
52 return Err(io::Error::new(
53 ErrorKind::InvalidInput,
54 format!("Insufficient permissions to signal process {pid}"),
55 ));
56 }
57 Err(ESRCH) => {
58 return Err(io::Error::new(
59 ErrorKind::InvalidInput,
60 format!("Process {pid} does not exist"),
61 ));
62 }
63 Err(e) => {
64 return Err(io::Error::new(
65 ErrorKind::InvalidInput,
66 format!("Unexpected error {e}"),
67 ));
68 }
69 };
70 Ok(())
71}