Try to gracefully terminal child process before using SIGKILL (#4890)
This commit is contained in:
parent
38b44f2496
commit
0999225794
|
@ -2529,6 +2529,7 @@ dependencies = [
|
|||
"indicatif 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"nix 0.14.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"reqwest 0.9.18 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"ring 0.13.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde 1.0.94 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
|
|
|
@ -24,6 +24,7 @@ dirs = "2.0.1"
|
|||
indicatif = "0.11.0"
|
||||
lazy_static = "1.3.0"
|
||||
log = "0.4.2"
|
||||
nix = "0.14.1"
|
||||
reqwest = "0.9.18"
|
||||
ring = "0.13.2"
|
||||
serde = "1.0.94"
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
use crate::config::Config;
|
||||
use crate::stop_process::stop_process;
|
||||
use crate::update_manifest::{SignedUpdateManifest, UpdateManifest};
|
||||
use chrono::{Local, TimeZone};
|
||||
use console::{style, Emoji};
|
||||
|
@ -793,8 +794,9 @@ pub fn run(
|
|||
Ok(true) => {
|
||||
// Update successful, kill current process so it will be restart
|
||||
if let Some(ref mut child) = child_option {
|
||||
let id = child.id();
|
||||
println!("Killing pid {}: {:?}", id, child.kill());
|
||||
stop_process(child).unwrap_or_else(|err| {
|
||||
eprintln!("Failed to stop child: {:?}", err);
|
||||
});
|
||||
}
|
||||
}
|
||||
Ok(false) => {} // No update available
|
||||
|
|
|
@ -8,6 +8,7 @@ mod build_env;
|
|||
mod command;
|
||||
mod config;
|
||||
mod defaults;
|
||||
mod stop_process;
|
||||
mod update_manifest;
|
||||
|
||||
// Return an error if a url cannot be parsed.
|
||||
|
|
|
@ -0,0 +1,67 @@
|
|||
use std::io;
|
||||
use std::process::Child;
|
||||
|
||||
fn kill_process(process: &mut Child) -> Result<(), io::Error> {
|
||||
if let Ok(()) = process.kill() {
|
||||
process.wait()?;
|
||||
} else {
|
||||
println!("Process {} has already exited", process.id());
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[cfg(windows)]
|
||||
pub fn stop_process(process: &mut Child) -> Result<(), io::Error> {
|
||||
kill_process(process)
|
||||
}
|
||||
|
||||
#[cfg(not(windows))]
|
||||
pub fn stop_process(process: &mut Child) -> Result<(), io::Error> {
|
||||
use nix::errno::Errno::{EINVAL, EPERM, ESRCH};
|
||||
use nix::sys::signal::{kill, Signal};
|
||||
use nix::unistd::Pid;
|
||||
use nix::Error::Sys;
|
||||
use std::io::ErrorKind;
|
||||
use std::thread;
|
||||
use std::time::{Duration, Instant};
|
||||
|
||||
let nice_wait = Duration::from_secs(5);
|
||||
let pid = Pid::from_raw(process.id() as i32);
|
||||
match kill(pid, Signal::SIGINT) {
|
||||
Ok(()) => {
|
||||
let expire = Instant::now() + nice_wait;
|
||||
while let Ok(None) = process.try_wait() {
|
||||
if Instant::now() > expire {
|
||||
break;
|
||||
}
|
||||
thread::sleep(nice_wait / 10);
|
||||
}
|
||||
if let Ok(None) = process.try_wait() {
|
||||
kill_process(process)?;
|
||||
}
|
||||
}
|
||||
Err(Sys(EINVAL)) => {
|
||||
println!("Invalid signal. Killing process {}", pid);
|
||||
kill_process(process)?;
|
||||
}
|
||||
Err(Sys(EPERM)) => {
|
||||
return Err(io::Error::new(
|
||||
ErrorKind::InvalidInput,
|
||||
format!("Insufficient permissions to signal process {}", pid),
|
||||
));
|
||||
}
|
||||
Err(Sys(ESRCH)) => {
|
||||
return Err(io::Error::new(
|
||||
ErrorKind::InvalidInput,
|
||||
format!("Process {} does not exist", pid),
|
||||
));
|
||||
}
|
||||
Err(e) => {
|
||||
return Err(io::Error::new(
|
||||
ErrorKind::InvalidInput,
|
||||
format!("Unexpected error {}", e),
|
||||
));
|
||||
}
|
||||
};
|
||||
Ok(())
|
||||
}
|
Loading…
Reference in New Issue