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)]
|
#[cfg(unix)]
|
||||||
pub fn install_handler<F>(handler: F)
|
pub fn install_handler<F>(handler: F)
|
||||||
where F: Fn() + 'static + Send + Sync {
|
where F: Fn() + 'static + Send + Sync {
|
||||||
|
@ -12,12 +18,14 @@ pub fn install_handler<F>(handler: F)
|
||||||
mask.add(SIGINT);
|
mask.add(SIGINT);
|
||||||
mask.thread_set_mask().expect("unable to set signal mask");
|
mask.thread_set_mask().expect("unable to set signal mask");
|
||||||
|
|
||||||
|
set_handler(handler);
|
||||||
|
|
||||||
// Spawn a thread to catch these signals
|
// Spawn a thread to catch these signals
|
||||||
thread::spawn(move || {
|
thread::spawn(move || {
|
||||||
let sig = mask.wait().expect("unable to sigwait");
|
let sig = mask.wait().expect("unable to sigwait");
|
||||||
|
|
||||||
// Invoke closure
|
// Invoke closure
|
||||||
handler();
|
invoke();
|
||||||
|
|
||||||
// Restore default behavior for received signal and unmask it
|
// Restore default behavior for received signal and unmask it
|
||||||
unsafe {
|
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)]
|
#[cfg(windows)]
|
||||||
pub fn install() -> Receiver<()> {
|
pub fn install_handler<F>(handler: F)
|
||||||
|
where F: Fn() + 'static + Send + Sync {
|
||||||
|
|
||||||
use kernel32::SetConsoleCtrlHandler;
|
use kernel32::SetConsoleCtrlHandler;
|
||||||
use winapi::{BOOL, DWORD, TRUE};
|
use winapi::{BOOL, DWORD, FALSE};
|
||||||
|
|
||||||
pub unsafe extern "system" fn ctrl_handler(_: DWORD) -> BOOL {
|
pub unsafe extern "system" fn ctrl_handler(_: DWORD) -> BOOL {
|
||||||
let _ = send_interrupt();
|
invoke();
|
||||||
TRUE
|
|
||||||
|
FALSE
|
||||||
}
|
}
|
||||||
|
|
||||||
let rx = create_channel();
|
set_handler(handler);
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
SetConsoleCtrlHandler(Some(ctrl_handler), TRUE);
|
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() {
|
fn main() {
|
||||||
let child_process: Arc<RwLock<Option<Process>>> = Arc::new(RwLock::new(None));
|
let child_process: Arc<RwLock<Option<Process>>> = Arc::new(RwLock::new(None));
|
||||||
|
|
||||||
let weak_child = Arc::downgrade(&child_process);
|
let weak_child = Arc::downgrade(&child_process);
|
||||||
|
|
||||||
interrupt::install_handler(move || {
|
interrupt::install_handler(move || {
|
||||||
if let Some(lock) = weak_child.upgrade() {
|
if let Some(lock) = weak_child.upgrade() {
|
||||||
let strong = lock.read().unwrap();
|
let strong = lock.read().unwrap();
|
||||||
|
@ -147,7 +147,7 @@ fn main() {
|
||||||
debug!("Path updated: {:?}", path);
|
debug!("Path updated: {:?}", path);
|
||||||
}
|
}
|
||||||
|
|
||||||
//. Wait for current child process to exit
|
// Wait for current child process to exit
|
||||||
{
|
{
|
||||||
let guard = child_process.read().unwrap();
|
let guard = child_process.read().unwrap();
|
||||||
|
|
||||||
|
@ -168,8 +168,8 @@ fn main() {
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
let mut lock = child_process.write().unwrap();
|
let mut guard = child_process.write().unwrap();
|
||||||
*lock = Process::new(&args.cmd, paths).ok();
|
*guard = Process::new(&args.cmd, paths).ok();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue