diff --git a/lib/cli/src/commands/mod.rs b/lib/cli/src/commands/mod.rs index 09021fbab88..1a0ea3abbfe 100644 --- a/lib/cli/src/commands/mod.rs +++ b/lib/cli/src/commands/mod.rs @@ -72,12 +72,21 @@ pub(crate) trait AsyncCliCommand: Send + Sync { async fn run_async(self) -> Result; - fn setup(&self) -> Option>> { + fn setup( + &self, + done: tokio::sync::oneshot::Receiver<()>, + ) -> Option>> { if is_terminal::IsTerminal::is_terminal(&std::io::stdin()) { return Some(tokio::task::spawn(async move { - tokio::signal::ctrl_c().await?; - let term = console::Term::stdout(); - let _ = term.show_cursor(); + tokio::select! { + _ = done => {} + + _ = tokio::signal::ctrl_c() => { + let term = console::Term::stdout(); + let _ = term.show_cursor(); + } + } + Ok::<(), anyhow::Error>(()) })); } @@ -91,12 +100,23 @@ impl> CliCommand for C { fn run(self) -> Result<(), anyhow::Error> { tokio::runtime::Runtime::new()?.block_on(async { - let handle = self.setup(); + let (snd, rcv) = tokio::sync::oneshot::channel(); + let handle = self.setup(rcv); - AsyncCliCommand::run_async(self).await?; + if let Err(e) = AsyncCliCommand::run_async(self).await { + if let Some(handle) = handle { + handle.abort(); + } + return Err(e); + } if let Some(handle) = handle { - handle.await??; + if snd.send(()).is_err() { + tracing::warn!("Failed to send 'done' signal to setup thread!"); + handle.abort(); + } else { + handle.await??; + } } Ok::<(), anyhow::Error>(())