summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorrabite <rabite@posteo.de>2019-08-02 00:38:41 +0200
committerrabite <rabite@posteo.de>2019-08-02 00:38:41 +0200
commit110322fad22d73216303a9e6a7ed610845f9b02e (patch)
tree2671b8913dbad17c44833f11ebdeb9768884d120
parent558857cc16fb16e8acaa95ed662b0bf9c91022f6 (diff)
improved subprocess killing with process groups
-rw-r--r--src/preview.rs39
-rw-r--r--src/proclist.rs19
2 files changed, 43 insertions, 15 deletions
diff --git a/src/preview.rs b/src/preview.rs
index 0e6dd3f..ef1fa48 100644
--- a/src/preview.rs
+++ b/src/preview.rs
@@ -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();
{
diff --git a/src/proclist.rs b/src/proclist.rs
index 1bc848c..b6926ca 100644
--- a/src/proclist.rs
+++ b/src/proclist.rs
@@ -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)),