Launch child processes in new process group

This commit is contained in:
Matt Green 2016-10-20 11:38:51 -04:00
parent f0650274a0
commit f3c6df8845
4 changed files with 47 additions and 5 deletions

3
Cargo.lock generated
View File

@ -1,10 +1,11 @@
[root]
name = "watchexec"
version = "1.1.0"
version = "1.1.1"
dependencies = [
"clap 2.14.0 (registry+https://github.com/rust-lang/crates.io-index)",
"env_logger 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
"glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.16 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
"notify 2.6.3 (registry+https://github.com/rust-lang/crates.io-index)",
]

View File

@ -15,6 +15,7 @@ lto = true
[dependencies]
glob = "0.2.11"
libc = "0.2.16"
log = "0.3.6"
notify = "2.6.3"

View File

@ -1,6 +1,9 @@
#![feature(process_exec)]
#[macro_use]
extern crate clap;
extern crate env_logger;
extern crate libc;
#[macro_use]
extern crate log;
extern crate notify;

View File

@ -1,3 +1,4 @@
use libc;
use std::process::{Child, Command};
pub struct Runner {
@ -11,7 +12,7 @@ impl Runner {
Runner {
process: None,
restart: restart,
cls: clear,
cls: clear
}
}
@ -25,6 +26,22 @@ impl Runner {
let _ = Command::new("clear").status();
}
#[cfg(target_family = "windows")]
fn kill(child: &mut Child) {
let _ = child.kill();
}
#[cfg(target_family = "unix")]
fn kill(child: &mut Child) {
extern {
fn killpg(pgrp: libc::pid_t, sig: libc::c_int) -> libc::c_int;
}
unsafe {
killpg(child.id() as i32, libc::SIGTERM);
}
}
#[cfg(target_family = "windows")]
fn invoke(&self, cmd: &str, updated_paths: Vec<&str>) -> Option<Child> {
let mut command = Command::new("cmd.exe");
@ -39,6 +56,8 @@ impl Runner {
#[cfg(target_family = "unix")]
fn invoke(&self, cmd: &str, updated_paths: Vec<&str>) -> Option<Child> {
use std::os::unix::process::CommandExt;
let mut command = Command::new("sh");
command.arg("-c").arg(cmd);
@ -46,18 +65,21 @@ impl Runner {
command.env("WATCHEXEC_UPDATED_PATH", updated_paths[0]);
}
command.spawn().ok()
command
.before_exec(|| unsafe { libc::setpgid(0, 0); Ok(()) })
.spawn()
.ok()
}
pub fn run_command(&mut self, cmd: &str, updated_paths: Vec<&str>) {
if let Some(ref mut child) = self.process {
if self.restart {
debug!("Killing child process (pid: {})", child.id());
let _ = child.kill();
Runner::kill(child);
}
debug!("Waiting for child process (pid: {})", child.id());
let _ = child.wait();
Runner::wait(child);
}
if self.cls {
@ -68,4 +90,19 @@ impl Runner {
self.process = self.invoke(cmd, updated_paths);
}
#[cfg(target_family = "windows")]
fn wait(child: &mut Child) {
let _ = child.wait();
}
#[cfg(target_family = "unix")]
fn wait(child: &mut Child) {
unsafe {
let pid = child.id() as i32;
let status: Box<i32> = Box::new(0);
libc::waitpid(-pid, Box::into_raw(status), 0);
}
}
}