Proper ctrl+c handling in Windows (fix #508)
This commit is contained in:
1
Cargo.lock
generated
1
Cargo.lock
generated
@@ -1843,6 +1843,7 @@ dependencies = [
|
|||||||
"toml",
|
"toml",
|
||||||
"walkdir",
|
"walkdir",
|
||||||
"which",
|
"which",
|
||||||
|
"winapi 0.3.9",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|||||||
@@ -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
22
src/ctrlc/interrupted.rs
Normal 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)
|
||||||
|
}
|
||||||
@@ -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::*;
|
||||||
|
|||||||
@@ -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.
|
||||||
|
|||||||
@@ -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")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -211,13 +211,9 @@ impl Terminal {
|
|||||||
.write_fmt(format_args!(
|
.write_fmt(format_args!(
|
||||||
"\n{}",
|
"\n{}",
|
||||||
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"),
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user