From 6523f6edf5f841b3484346315eb05b86a2858f24 Mon Sep 17 00:00:00 2001 From: Matt Green Date: Wed, 9 Nov 2016 17:00:24 -0500 Subject: [PATCH] Cleanup, initial Windows implementation of interrupt handler --- src/interrupt.rs | 40 ++++++++++++++++++++++++++++++---------- src/main.rs | 8 ++++---- 2 files changed, 34 insertions(+), 14 deletions(-) diff --git a/src/interrupt.rs b/src/interrupt.rs index 18034ae..fc56abe 100644 --- a/src/interrupt.rs +++ b/src/interrupt.rs @@ -1,3 +1,9 @@ +use std::sync::Mutex; + +lazy_static! { + static ref CLEANUP: Mutex>> = Mutex::new(None); +} + #[cfg(unix)] pub fn install_handler(handler: F) where F: Fn() + 'static + Send + Sync { @@ -12,12 +18,14 @@ pub fn install_handler(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(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(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(handler: F) + where F: Fn() + 'static + Send + Sync { + + *CLEANUP.lock().unwrap() = Some(Box::new(handler)); } diff --git a/src/main.rs b/src/main.rs index e43668e..badaa3d 100644 --- a/src/main.rs +++ b/src/main.rs @@ -80,8 +80,8 @@ fn init_logger(debug: bool) { fn main() { let child_process: Arc>> = 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(); } } }