mirror of
https://github.com/watchexec/watchexec.git
synced 2024-09-28 22:21:33 +02:00
Cleanup, initial Windows implementation of interrupt handler
This commit is contained in:
parent
cf0a98b7a5
commit
6523f6edf5
@ -1,3 +1,9 @@
|
||||
use std::sync::Mutex;
|
||||
|
||||
lazy_static! {
|
||||
static ref CLEANUP: Mutex<Option<Box<Fn() + Send>>> = Mutex::new(None);
|
||||
}
|
||||
|
||||
#[cfg(unix)]
|
||||
pub fn install_handler<F>(handler: F)
|
||||
where F: Fn() + 'static + Send + Sync {
|
||||
@ -12,12 +18,14 @@ pub fn install_handler<F>(handler: F)
|
||||
mask.add(SIGINT);
|
||||
mask.thread_set_mask().expect("unable to set signal mask");
|
||||
|
||||
set_handler(handler);
|
||||
|
||||
// Spawn a thread to catch these signals
|
||||
thread::spawn(move || {
|
||||
let sig = mask.wait().expect("unable to sigwait");
|
||||
|
||||
// Invoke closure
|
||||
handler();
|
||||
invoke();
|
||||
|
||||
// Restore default behavior for received signal and unmask it
|
||||
unsafe {
|
||||
@ -33,22 +41,34 @@ pub fn install_handler<F>(handler: F)
|
||||
});
|
||||
}
|
||||
|
||||
/// On Windows, use SetConsoleCtrlHandler() to send an interrupt
|
||||
/// SetConsoleCtrlHandler runs in it's own thread, so it's safe.
|
||||
#[cfg(windows)]
|
||||
pub fn install() -> Receiver<()> {
|
||||
pub fn install_handler<F>(handler: F)
|
||||
where F: Fn() + 'static + Send + Sync {
|
||||
|
||||
use kernel32::SetConsoleCtrlHandler;
|
||||
use winapi::{BOOL, DWORD, TRUE};
|
||||
use winapi::{BOOL, DWORD, FALSE};
|
||||
|
||||
pub unsafe extern "system" fn ctrl_handler(_: DWORD) -> BOOL {
|
||||
let _ = send_interrupt();
|
||||
TRUE
|
||||
invoke();
|
||||
|
||||
FALSE
|
||||
}
|
||||
|
||||
let rx = create_channel();
|
||||
set_handler(handler);
|
||||
|
||||
unsafe {
|
||||
SetConsoleCtrlHandler(Some(ctrl_handler), TRUE);
|
||||
}
|
||||
|
||||
rx
|
||||
}
|
||||
|
||||
fn invoke() {
|
||||
if let Some(ref handler) = *CLEANUP.lock().unwrap() {
|
||||
handler()
|
||||
}
|
||||
}
|
||||
|
||||
fn set_handler<F>(handler: F)
|
||||
where F: Fn() + 'static + Send + Sync {
|
||||
|
||||
*CLEANUP.lock().unwrap() = Some(Box::new(handler));
|
||||
}
|
||||
|
@ -80,8 +80,8 @@ fn init_logger(debug: bool) {
|
||||
|
||||
fn main() {
|
||||
let child_process: Arc<RwLock<Option<Process>>> = Arc::new(RwLock::new(None));
|
||||
|
||||
let weak_child = Arc::downgrade(&child_process);
|
||||
|
||||
interrupt::install_handler(move || {
|
||||
if let Some(lock) = weak_child.upgrade() {
|
||||
let strong = lock.read().unwrap();
|
||||
@ -147,7 +147,7 @@ fn main() {
|
||||
debug!("Path updated: {:?}", path);
|
||||
}
|
||||
|
||||
//. Wait for current child process to exit
|
||||
// Wait for current child process to exit
|
||||
{
|
||||
let guard = child_process.read().unwrap();
|
||||
|
||||
@ -168,8 +168,8 @@ fn main() {
|
||||
}
|
||||
|
||||
{
|
||||
let mut lock = child_process.write().unwrap();
|
||||
*lock = Process::new(&args.cmd, paths).ok();
|
||||
let mut guard = child_process.write().unwrap();
|
||||
*guard = Process::new(&args.cmd, paths).ok();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user