diff --git a/Cargo.lock b/Cargo.lock index cc594b6356..5bc9a66d90 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2496,6 +2496,7 @@ dependencies = [ "reedline", "rstest", "serial_test", + "signal-hook", "tempfile", "winres", ] diff --git a/Cargo.toml b/Cargo.toml index 0e11e7296e..d7d55376c3 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -60,6 +60,7 @@ is_executable = "1.0.1" [target.'cfg(not(target_os = "windows"))'.dependencies] # Our dependencies don't use OpenSSL on Windows openssl = { version = "0.10.38", features = ["vendored"], optional = true } +signal-hook = { version = "0.3.14", default-features = false } [dev-dependencies] nu-test-support = { path="./crates/nu-test-support", version = "0.63.1" } @@ -118,4 +119,3 @@ debug = false [[bin]] name = "nu" path = "src/main.rs" - diff --git a/crates/nu-cli/src/repl.rs b/crates/nu-cli/src/repl.rs index 6e8c8ff9a9..c29335516b 100644 --- a/crates/nu-cli/src/repl.rs +++ b/crates/nu-cli/src/repl.rs @@ -113,6 +113,10 @@ pub fn evaluate_repl( if let Some(ctrlc) = &mut engine_state.ctrlc { ctrlc.store(false, Ordering::SeqCst); } + // Reset the SIGQUIT handler + if let Some(sig_quit) = engine_state.get_sig_quit() { + sig_quit.store(false, Ordering::SeqCst); + } config = engine_state.get_config(); diff --git a/crates/nu-protocol/src/engine/engine_state.rs b/crates/nu-protocol/src/engine/engine_state.rs index 98bc7709d0..bb96c9122e 100644 --- a/crates/nu-protocol/src/engine/engine_state.rs +++ b/crates/nu-protocol/src/engine/engine_state.rs @@ -75,6 +75,8 @@ pub struct EngineState { pub config: Config, #[cfg(feature = "plugin")] pub plugin_signatures: Option, + #[cfg(not(windows))] + sig_quit: Option>, } pub const NU_VARIABLE_ID: usize = 0; @@ -106,6 +108,8 @@ impl EngineState { config: Config::default(), #[cfg(feature = "plugin")] plugin_signatures: None, + #[cfg(not(windows))] + sig_quit: None, } } @@ -713,6 +717,21 @@ impl EngineState { self.num_files() - 1 } + + #[cfg(not(windows))] + pub fn get_sig_quit(&self) -> &Option> { + &self.sig_quit + } + + #[cfg(windows)] + pub fn get_sig_quit(&self) -> &Option> { + &None + } + + #[cfg(not(windows))] + pub fn set_sig_quit(&mut self, sig_quit: Arc) { + self.sig_quit = Some(sig_quit) + } } /// A temporary extension to the global state. This handles bridging between the global state and the diff --git a/src/main.rs b/src/main.rs index b9b154a8ec..09c67d12da 100644 --- a/src/main.rs +++ b/src/main.rs @@ -73,6 +73,16 @@ fn main() -> Result<()> { engine_state.ctrlc = Some(engine_state_ctrlc); // End ctrl-c protection section + // SIGQUIT protection section (only works for POSIX system) + #[cfg(not(windows))] + { + use signal_hook::consts::SIGQUIT; + let sig_quit = Arc::new(AtomicBool::new(false)); + signal_hook::flag::register(SIGQUIT, sig_quit.clone()).expect("Error setting SIGQUIT flag"); + engine_state.set_sig_quit(sig_quit); + } + // End SIGQUIT protection section + let mut args_to_nushell = vec![]; let mut script_name = String::new(); let mut args_to_script = vec![];