mirror of
https://github.com/nushell/nushell.git
synced 2025-08-15 09:53:13 +02:00
Kill background jobs on interrupt (#16285)
# Description This PR kills all background jobs on interrupt, as a fix for https://github.com/nushell/nushell/issues/15947. # User-Facing Changes If you run the following: `job spawn { print "job spawned"; ^sleep infinity }; ^sleep infinity`, then hit ctrl-c, the current behavior is that the `sleep` process from the job will not be killed, it will reparented to init. With this change, the process will be killed on ctrl-c. # Tests + Formatting I was unsure of the best way to write a test for this. # After Submitting --------- Co-authored-by: 132ikl <132@ikl.sh>
This commit is contained in:
@ -68,6 +68,19 @@ impl Handlers {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Registers a new handler which persists for the entire process lifetime.
|
||||||
|
///
|
||||||
|
/// Only use this for handlers which should exist for the lifetime of the program.
|
||||||
|
/// You should prefer to use `register` with a `HandlerGuard` when possible.
|
||||||
|
pub fn register_unguarded(&self, handler: Handler) -> Result<(), ShellError> {
|
||||||
|
let id = self.next_id.next()?;
|
||||||
|
if let Ok(mut handlers) = self.handlers.lock() {
|
||||||
|
handlers.push((id, handler));
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
/// Runs all registered handlers.
|
/// Runs all registered handlers.
|
||||||
pub fn run(&self, action: SignalAction) {
|
pub fn run(&self, action: SignalAction) {
|
||||||
if let Ok(handlers) = self.handlers.lock() {
|
if let Ok(handlers) = self.handlers.lock() {
|
||||||
|
@ -9,6 +9,21 @@ pub(crate) fn ctrlc_protection(engine_state: &mut EngineState) {
|
|||||||
engine_state.set_signals(Signals::new(interrupt.clone()));
|
engine_state.set_signals(Signals::new(interrupt.clone()));
|
||||||
|
|
||||||
let signal_handlers = Handlers::new();
|
let signal_handlers = Handlers::new();
|
||||||
|
|
||||||
|
// Register a handler to kill all background jobs on interrupt.
|
||||||
|
signal_handlers
|
||||||
|
.register_unguarded({
|
||||||
|
let jobs = engine_state.jobs.clone();
|
||||||
|
Box::new(move |action| {
|
||||||
|
if action == SignalAction::Interrupt {
|
||||||
|
if let Ok(mut jobs) = jobs.lock() {
|
||||||
|
let _ = jobs.kill_all();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
||||||
|
.expect("Failed to register interrupt signal handler");
|
||||||
|
|
||||||
engine_state.signal_handlers = Some(signal_handlers.clone());
|
engine_state.signal_handlers = Some(signal_handlers.clone());
|
||||||
|
|
||||||
ctrlc::set_handler(move || {
|
ctrlc::set_handler(move || {
|
||||||
|
Reference in New Issue
Block a user