Skip to content

Commit

Permalink
feat: Kill all child processes when shell received CTRL-C
Browse files Browse the repository at this point in the history
  • Loading branch information
mo committed Nov 12, 2024
1 parent 86b6b3a commit c1f6b12
Show file tree
Hide file tree
Showing 2 changed files with 30 additions and 17 deletions.
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ anyhow = "1.0.75"
futures = { version = "0.3.29", optional = true }
glob = { version = "0.3.1", optional = true }
path-dedot = { version = "3.1.1", optional = true }
tokio = { version = "1", features = ["fs", "io-std", "io-util", "macros", "process", "rt-multi-thread", "sync", "time"], optional = true }
tokio = { version = "1", features = ["fs", "io-std", "io-util", "macros", "process", "rt-multi-thread", "sync", "time", "signal"], optional = true }
tokio-util = { version = "0.7.10", optional = true }
os_pipe = { version = "1.1.4", optional = true }
serde = { version = "1", features = ["derive"], optional = true }
Expand Down
45 changes: 29 additions & 16 deletions src/shell/commands/executable.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ use crate::FutureExecuteResult;
use crate::ShellCommand;
use crate::ShellCommandContext;
use futures::FutureExt;
use std::sync::Arc;
use tokio::sync::Mutex;

/// Command that resolves the command name and
/// executes it in a separate process.
Expand Down Expand Up @@ -41,8 +43,8 @@ impl ShellCommand for ExecutableCommand {
.stderr(stderr.clone().into_stdio())
.spawn();

let mut child = match child {
Ok(child) => child,
let child = match child {
Ok(child) => Arc::new(Mutex::new(child)),
Err(err) => {
let _ = stderr.write_line(&format!(
"Error launching '{}': {}",
Expand All @@ -55,22 +57,33 @@ impl ShellCommand for ExecutableCommand {
// avoid deadlock since this is holding onto the pipes
drop(sub_command);

tokio::select! {
result = child.wait() => match result {
Ok(status) => ExecuteResult::Continue(
status.code().unwrap_or(1),
Vec::new(),
Vec::new(),
),
Err(err) => {
let _ = stderr.write_line(&format!("{}", err));
ExecuteResult::Continue(1, Vec::new(), Vec::new())
}
},
_ = context.state.token().cancelled() => {
let child_clone = Arc::clone(&child);

tokio::spawn(async move {
tokio::signal::ctrl_c().await.unwrap();
let mut child = child_clone.lock().await;
if let Ok(None) = child.try_wait() {
let _ = child.kill().await;
ExecuteResult::for_cancellation()
}
});

let mut child_locked = child.lock().await;
tokio::select! {
result = child_locked.wait() => match result {
Ok(status) => ExecuteResult::Continue(
status.code().unwrap_or(1),
Vec::new(),
Vec::new(),
),
Err(err) => {
let _ = stderr.write_line(&format!("{}", err));
ExecuteResult::Continue(1, Vec::new(), Vec::new())
}
},
_ = context.state.token().cancelled() => {
let _ = child_locked.kill().await;
ExecuteResult::for_cancellation()
}
}
}
.boxed_local()
Expand Down

0 comments on commit c1f6b12

Please sign in to comment.