Proper ctrl+c handling in Windows (fix #508)

This commit is contained in:
Roey Darwish Dror
2020-08-26 22:30:19 +03:00
parent 4657160f80
commit 1317e51096
7 changed files with 53 additions and 35 deletions

1
Cargo.lock generated
View File

@@ -1843,6 +1843,7 @@ dependencies = [
"toml", "toml",
"walkdir", "walkdir",
"which", "which",
"winapi 0.3.9",
] ]
[[package]] [[package]]

View File

@@ -43,6 +43,7 @@ self_update_crate = { version = "0.19.0", optional = true, package = "self_upda
[target.'cfg(windows)'.dependencies] [target.'cfg(windows)'.dependencies]
self_update_crate = { version = "0.19.0", optional = true, package = "self_update", features = ["archive-zip", "compression-zip-deflate"] } self_update_crate = { version = "0.19.0", optional = true, package = "self_update", features = ["archive-zip", "compression-zip-deflate"] }
winapi = "0.3.9"
[target.'cfg(target_os = "linux")'.dependencies] [target.'cfg(target_os = "linux")'.dependencies]
rust-ini = "0.15.0" rust-ini = "0.15.0"

22
src/ctrlc/interrupted.rs Normal file
View File

@@ -0,0 +1,22 @@
use lazy_static::lazy_static;
use std::sync::atomic::{AtomicBool, Ordering};
lazy_static! {
/// A global variable telling whether the application has been interrupted.
static ref INTERRUPTED: AtomicBool = AtomicBool::new(false);
}
/// Tells whether the program has been interrupted
pub fn interrupted() -> bool {
INTERRUPTED.load(Ordering::SeqCst)
}
/// Clears the interrupted flag
pub fn unset_interrupted() {
debug_assert!(INTERRUPTED.load(Ordering::SeqCst));
INTERRUPTED.store(false, Ordering::SeqCst)
}
pub fn set_interrupted() {
INTERRUPTED.store(true, Ordering::SeqCst)
}

View File

@@ -1,11 +1,13 @@
//! Provides handling for process interruption. mod interrupted;
//! There's no actual handling for Windows at the moment.
#[cfg(unix)] #[cfg(unix)]
mod unix; mod unix;
#[cfg(unix)] #[cfg(unix)]
pub use self::unix::*; pub use self::unix::set_handler;
#[cfg(windows)] #[cfg(windows)]
mod windows; mod windows;
#[cfg(windows)] #[cfg(windows)]
pub use self::windows::*; pub use self::windows::set_handler;
pub use self::interrupted::*;

View File

@@ -1,27 +1,10 @@
//! SIGINT handling in Unix systems. //! SIGINT handling in Unix systems.
use lazy_static::lazy_static; use crate::ctrlc::interrupted::set_interrupted;
use nix::sys::signal; use nix::sys::signal;
use std::sync::atomic::{AtomicBool, Ordering};
lazy_static! {
/// A global variable telling whether the application has been interrupted.
static ref INTERRUPTED: AtomicBool = AtomicBool::new(false);
}
/// Tells whether the program has been interrupted
pub fn interrupted() -> bool {
INTERRUPTED.load(Ordering::SeqCst)
}
/// Clears the interrupted flag
pub fn unset_interrupted() {
debug_assert!(INTERRUPTED.load(Ordering::SeqCst));
INTERRUPTED.store(false, Ordering::SeqCst)
}
/// Handle SIGINT. Set the interruption flag. /// Handle SIGINT. Set the interruption flag.
extern "C" fn handle_sigint(_: i32) { extern "C" fn handle_sigint(_: i32) {
INTERRUPTED.store(true, Ordering::SeqCst) set_interrupted()
} }
/// Set the necessary signal handlers. /// Set the necessary signal handlers.

View File

@@ -1,9 +1,21 @@
//! A stub for Ctrl + C handling. //! A stub for Ctrl + C handling.
use crate::ctrlc::interrupted::set_interrupted;
use winapi::shared::minwindef::{BOOL, DWORD, FALSE, TRUE};
use winapi::um::consoleapi::SetConsoleCtrlHandler;
use winapi::um::wincon::CTRL_C_EVENT;
pub fn interrupted() -> bool { extern "system" fn handler(ctrl_type: DWORD) -> BOOL {
false match ctrl_type {
CTRL_C_EVENT => {
set_interrupted();
TRUE
}
_ => FALSE,
}
} }
pub fn unset_interrupted() {} pub fn set_handler() {
if 0 == unsafe { SetConsoleCtrlHandler(Some(handler), TRUE) } {
pub fn set_handler() {} log::error!("Cannot set a control C handler")
}
}

View File

@@ -213,11 +213,7 @@ impl Terminal {
style(format!( style(format!(
"{}Retry? (y)es/(N)o/(s)hell{}", "{}Retry? (y)es/(N)o/(s)hell{}",
self.prefix, self.prefix,
if interrupted { if interrupted { "/(q)uit" } else { "" }
"(Press Ctrl+C again to stop Topgrade) "
} else {
""
}
)) ))
.yellow() .yellow()
.bold() .bold()
@@ -233,7 +229,8 @@ impl Terminal {
break Ok(true); break Ok(true);
} }
'n' | 'N' | '\r' | '\n' => break Ok(false), 'n' | 'N' | '\r' | '\n' => break Ok(false),
_ => (), 'q' | 'Q' => return Err(io::Error::from(io::ErrorKind::Interrupted)),
_ => println!("hi"),
} }
}; };