improved subprocess killing with process groups

This commit is contained in:
rabite 2019-08-02 00:38:41 +02:00
parent 558857cc16
commit 110322fad2
2 changed files with 43 additions and 15 deletions

View File

@ -16,8 +16,8 @@ use crate::imgview::ImgView;
use crate::mediaview::MediaView;
pub type AsyncWidgetFn<W> = FnOnce(&Stale, WidgetCore)
-> HResult<W> + Send + Sync;
pub type AsyncWidgetFn<W> = dyn FnOnce(&Stale, WidgetCore)
-> HResult<W> + Send + Sync;
lazy_static! {
static ref SUBPROC: Arc<Mutex<Option<u32>>> = { Arc::new(Mutex::new(None)) };
@ -26,7 +26,19 @@ lazy_static! {
fn kill_proc() -> HResult<()> {
let mut pid = SUBPROC.lock()?;
pid.map(|pid|
unsafe { libc::kill(pid as i32, 15); }
// Do this in another thread so we can wait on process to exit with SIGHUP
std::thread::spawn(move || {
let sleep_time = std::time::Duration::from_millis(50);
// Here be dragons
unsafe {
// Kill using process group, to clean up all child processes, too
// 15 = SIGTERM, 9 = SIGKILL
libc::killpg(pid as i32, 15);
std::thread::sleep(sleep_time);
libc::killpg(pid as i32, 9);
}
})
);
*pid = None;
Ok(())
@ -499,13 +511,22 @@ impl Previewer {
}
fn run_external(cmd: PathBuf, file: &File, stale: &Stale) -> HResult<Vec<String>> {
let process =
use std::os::unix::process::CommandExt;
let process = unsafe {
std::process::Command::new(cmd)
.arg(&file.path)
.stdin(std::process::Stdio::null())
.stdout(std::process::Stdio::piped())
.stderr(std::process::Stdio::null())
.spawn()?;
.arg(&file.path)
.stdin(std::process::Stdio::null())
.stdout(std::process::Stdio::piped())
.stderr(std::process::Stdio::null())
.pre_exec(|| {
let pid = std::process::id();
// To make killing subprocess possible create new process group
libc::setpgid(pid as i32, pid as i32);
Ok(())
})
.spawn()?
};
let pid = process.id();
{

View File

@ -155,6 +155,9 @@ impl Process {
sender.send(Events::Status(status))?;
stdout.consume(len);
// Wait a bit so hunter doesn't explode
std::thread::sleep(std::time::Duration::from_millis(100));
}
};
processor(&cmd, &sender).log();
@ -268,12 +271,16 @@ impl ListView<Vec<Process>> {
self.core.show_status(&format!("Running: {}", &short_cmd)).log();
let handle = Command::new(real_cmd)
.args(args)
.stdin(std::process::Stdio::null())
.stdout(std::process::Stdio::piped())
.before_exec(|| unsafe { libc::dup2(1, 2); Ok(()) })
.spawn()?;
// Need pre_exec here to interleave stderr with stdout
let handle = unsafe {
Command::new(real_cmd)
.args(args)
.stdin(std::process::Stdio::null())
.stdout(std::process::Stdio::piped())
// Without this stderr would be separate which is no good for procview
.pre_exec(|| { libc::dup2(1, 2); Ok(()) })
.spawn()?
};
let mut proc = Process {
cmd: short_cmd,
handle: Arc::new(Mutex::new(handle)),