mirror of
https://github.com/nushell/nushell.git
synced 2025-08-15 01:33:06 +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.
|
||||
pub fn run(&self, action: SignalAction) {
|
||||
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()));
|
||||
|
||||
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());
|
||||
|
||||
ctrlc::set_handler(move || {
|
||||
|
Reference in New Issue
Block a user