diff --git a/Makefile b/Makefile
index ad9b2d4..191b450 100644
--- a/Makefile
+++ b/Makefile
@@ -1,6 +1,6 @@
VER=$(shell grep version Cargo.toml | head -n1 | grep -Eow '".+"' | sed 's/"//g')
-.PHONY: doc
+.PHONY: doc test
debug: src/* Cargo.toml
@cargo build
diff --git a/README.md b/README.md
index 6fb9581..ba6ae72 100644
--- a/README.md
+++ b/README.md
@@ -54,6 +54,10 @@ Call/restart `python server.py` when any Python file in the current directory (a
$ watchexec -e py -r python server.py
+Call/restart `my_server` when any file in the current directory (and all subdirectories) changes, sending `SIGKILL` to stop the child process:
+
+ $ watchexec -r -k my_server
+
Run `make` when any file changes, using the `.gitignore` file in the current directory to filter:
$ watchexec make
diff --git a/doc/watchexec.1 b/doc/watchexec.1
index 0c89eda..1450ca1 100644
--- a/doc/watchexec.1
+++ b/doc/watchexec.1
@@ -1,7 +1,7 @@
.\" generated with Ronn/v0.7.3
.\" http://github.com/rtomayko/ronn/tree/0.7.3
.
-.TH "WATCHEXEC" "1" "November 2016" "" ""
+.TH "WATCHEXEC" "1" "December 2016" "" ""
.
.SH "NAME"
\fBwatchexec\fR \- execute commands when watched files change
@@ -30,12 +30,16 @@ Comma\-separated list of file extensions to filter by\. Leading dots are allowed
Ignores modifications from paths that do not match \fIpattern\fR\. This option can be specified multiple times, where a match on any given pattern causes the path to trigger \fIcommand\fR\.
.
.TP
+\fB\-k\fR, \fB\-\-kill\fR
+Send \fBSIGKILL\fR to the child process group instead of \fBSIGTERM\fR\.
+.
+.TP
\fB\-i\fR, \fB\-\-ignore\fR \fIpattern\fR
Ignores modifications from paths that match \fIpattern\fR\. This option can be specified multiple times, and a match on any pattern causes the path to be ignored\.
.
.TP
\fB\-r\fR, \fB\-\-restart\fR
-Sends \fBSIGTERM\fR to the child process if it is still running when subsequent file modifications are detected, then waits for the child to exit\.
+Terminates the child process group if it is still running when subsequent file modifications are detected\. By default, sends \fBSIGTERM\fR; use \fB\-\-kill\fR to send \fBSIGKILL\fR\.
.
.TP
\fB\-c\fR, \fB\-\-clear\fR
diff --git a/doc/watchexec.1.html b/doc/watchexec.1.html
index 5594776..e077623 100644
--- a/doc/watchexec.1.html
+++ b/doc/watchexec.1.html
@@ -88,8 +88,9 @@
cmdCommand to run when watched files are modified, and at startup, unless --postpone
is specified. All arguments are passed to cmd.
-e
, --exts
extensionsComma-separated list of file extensions to filter by. Leading dots are allowed (.rs) are allowed. (This is a shorthand for -f
).
-f
, --filter
patternIgnores modifications from paths that do not match pattern. This option can be specified multiple times, where a match on any given pattern causes the path to trigger command.
+-k
, --kill
Send SIGKILL
to the child process group instead of SIGTERM
.
-i
, --ignore
patternIgnores modifications from paths that match pattern. This option can be specified multiple times, and a match on any pattern causes the path to be ignored.
--r
, --restart
Sends SIGTERM
to the child process if it is still running when subsequent file modifications are detected, then waits for the child to exit.
+-r
, --restart
Terminates the child process group if it is still running when subsequent file modifications are detected. By default, sends SIGTERM
; use --kill
to send SIGKILL
.
-c
, --clear
Clears the screen before executing command.
-p
, --postpone
Postpone execution of command until the first file modification is detected.
-d
, --debug
Prints diagnostic messages to STDERR
@@ -127,7 +128,7 @@
diff --git a/doc/watchexec.1.ronn b/doc/watchexec.1.ronn
index f25a05b..48dc309 100644
--- a/doc/watchexec.1.ronn
+++ b/doc/watchexec.1.ronn
@@ -22,11 +22,14 @@ Comma-separated list of file extensions to filter by. Leading dots are allowed (
* `-f`, `--filter` :
Ignores modifications from paths that do not match . This option can be specified multiple times, where a match on any given pattern causes the path to trigger *command*.
+* `-k`, `--kill`:
+Send `SIGKILL` to the child process group instead of `SIGTERM`.
+
* `-i`, `--ignore` *pattern*:
Ignores modifications from paths that match . This option can be specified multiple times, and a match on any pattern causes the path to be ignored.
* `-r`, `--restart`:
-Sends `SIGTERM` to the child process if it is still running when subsequent file modifications are detected, then waits for the child to exit.
+Terminates the child process group if it is still running when subsequent file modifications are detected. By default, sends `SIGTERM`; use `--kill` to send `SIGKILL`.
* `-c`, `--clear`:
Clears the screen before executing .
diff --git a/src/cli.rs b/src/cli.rs
index c8afc77..5ff75ec 100644
--- a/src/cli.rs
+++ b/src/cli.rs
@@ -9,6 +9,7 @@ pub struct Args {
pub filters: Vec,
pub ignores: Vec,
pub clear_screen: bool,
+ pub kill: bool,
pub restart: bool,
pub debug: bool,
pub run_initially: bool,
@@ -81,6 +82,9 @@ pub fn get_args() -> Args {
.help("Forces polling mode")
.long("force-poll")
.value_name("interval"))
+ .arg(Arg::with_name("kill")
+ .help("Send SIGKILL to child processes")
+ .long("kill"))
.get_matches();
let cmd = values_t!(args.values_of("command"), String).unwrap().join(" ");
@@ -115,6 +119,7 @@ pub fn get_args() -> Args {
filters: filters,
ignores: ignores,
clear_screen: args.is_present("clear"),
+ kill: args.is_present("kill"),
restart: args.is_present("restart"),
debug: args.is_present("debug"),
run_initially: !args.is_present("postpone"),
diff --git a/src/main.rs b/src/main.rs
index d12b66b..d44e8b7 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -79,8 +79,10 @@ fn init_logger(debug: bool) {
}
fn main() {
+ let args = cli::get_args();
let child_process: Arc>> = Arc::new(RwLock::new(None));
let weak_child = Arc::downgrade(&child_process);
+ let kill = args.kill;
signal::install_handler(move |sig: Signal| {
if let Some(lock) = weak_child.upgrade() {
@@ -88,7 +90,12 @@ fn main() {
if let Some(ref child) = *strong {
match sig {
Signal::Terminate => {
- child.kill();
+ if kill {
+ child.kill();
+ } else {
+ child.terminate();
+ }
+
child.wait();
},
Signal::Stop => {
@@ -102,8 +109,6 @@ fn main() {
}
});
- let args = cli::get_args();
-
init_logger(args.debug);
let cwd = env::current_dir()
diff --git a/src/process.rs b/src/process.rs
index ea23875..a147e66 100644
--- a/src/process.rs
+++ b/src/process.rs
@@ -8,8 +8,7 @@ pub use self::imp::Process;
#[cfg(target_family = "unix")]
mod imp {
- use libc::c_int;
- use libc::pid_t;
+ use libc::*;
use std::io::Result;
use std::path::PathBuf;
use std::process::Command;
@@ -20,7 +19,6 @@ mod imp {
impl Process {
pub fn new(cmd: &str, updated_paths: Vec) -> Result {
- use libc::exit;
use nix::unistd::*;
use std::fs::File;
use std::io;
@@ -80,27 +78,19 @@ mod imp {
}
pub fn kill(&self) {
- use libc::SIGTERM;
-
- self.signal(SIGTERM);
+ self.signal(SIGKILL);
}
pub fn pause(&self) {
- use libc::SIGTSTP;
-
self.signal(SIGTSTP);
}
pub fn resume(&self) {
- use libc::SIGCONT;
-
self.signal(SIGCONT);
}
fn signal(&self, sig: c_int) {
- use libc::*;
-
extern "C" {
fn killpg(pgrp: pid_t, sig: c_int) -> c_int;
}
@@ -111,6 +101,10 @@ mod imp {
}
+ pub fn terminate(&self) {
+ self.signal(SIGTERM);
+ }
+
pub fn wait(&self) {
use nix::sys::wait::waitpid;
@@ -181,9 +175,7 @@ mod imp {
}
pub fn kill(&self) {
- unsafe {
- let _ = TerminateJobObject(self.job, 1);
- }
+ self.terminate();
}
pub fn pause(&self) {
@@ -192,6 +184,13 @@ mod imp {
pub fn resume(&self) {
}
+ pub fn terminate(&self) {
+ unsafe {
+ let _ = TerminateJobObject(self.job, 1);
+ }
+ }
+
+
pub fn wait(&self) {
unsafe {
let _ = WaitForSingleObject(self.job, INFINITE);