Cleanup, initial Windows implementation of interrupt handler

This commit is contained in:
Matt Green 2016-11-09 17:00:24 -05:00
parent cf0a98b7a5
commit 6523f6edf5
2 changed files with 34 additions and 14 deletions

View File

@ -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));
}

View File

@ -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();
}
}
}