just/src/interrupt_handler.rs
Casey Rodarmor 1cb90f4e65
Use pub(crate) instead of pub (#471)
Eventually, there will probably be a `crate` visibility specifier that
does the same thing as `pub(crate)`. This commit replaces `pub` with
`pub(crate)`, so when `crate` is available we can easily switch to it.
2019-09-21 15:35:03 -07:00

77 lines
1.5 KiB
Rust

use crate::common::*;
pub(crate) struct InterruptHandler {
blocks: u32,
interrupted: bool,
}
impl InterruptHandler {
pub(crate) fn install() -> Result<(), ctrlc::Error> {
ctrlc::set_handler(|| InterruptHandler::instance().interrupt())
}
pub(crate) fn instance() -> MutexGuard<'static, InterruptHandler> {
lazy_static! {
static ref INSTANCE: Mutex<InterruptHandler> = Mutex::new(InterruptHandler::new());
}
match INSTANCE.lock() {
Ok(guard) => guard,
Err(poison_error) => die!(
"{}",
RuntimeError::Internal {
message: format!("interrupt handler mutex poisoned: {}", poison_error),
}
),
}
}
fn new() -> InterruptHandler {
InterruptHandler {
blocks: 0,
interrupted: false,
}
}
fn interrupt(&mut self) {
self.interrupted = true;
if self.blocks > 0 {
return;
}
Self::exit();
}
fn exit() {
process::exit(130);
}
pub(crate) fn block(&mut self) {
self.blocks += 1;
}
pub(crate) fn unblock(&mut self) {
if self.blocks == 0 {
die!(
"{}",
RuntimeError::Internal {
message: "attempted to unblock interrupt handler, but handler was not blocked"
.to_string(),
}
);
}
self.blocks -= 1;
if self.interrupted {
Self::exit();
}
}
pub(crate) fn guard<T, F: FnOnce() -> T>(function: F) -> T {
let _guard = InterruptGuard::new();
function()
}
}