From 403b912767cbeb6f415ea82c6e9aa142a9ae6461 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=99=BD=E5=B1=B1=E9=A2=A8=E9=9C=B2?= Date: Fri, 29 Mar 2024 00:36:28 +0900 Subject: [PATCH] Windows: Implement signal in collab (#9918) Only `CtrlC` and `CtrlBreak` signals are supported. `CtrlLogoff` and `CtrlShutdown` is service only signal and I have not tried these yet. `CtrlClose` occurs when terminal window is closed, but I found tokio's `ctrl_close` does not work well, so I put comment in code. Release Notes: - N/A --- crates/collab/src/main.rs | 40 +++++++++++++++++++++++++++------------ 1 file changed, 28 insertions(+), 12 deletions(-) diff --git a/crates/collab/src/main.rs b/crates/collab/src/main.rs index 7f25e74560..728544c533 100644 --- a/crates/collab/src/main.rs +++ b/crates/collab/src/main.rs @@ -137,18 +137,38 @@ async fn main() -> Result<()> { ); #[cfg(unix)] + let signal = async move { + let mut sigterm = tokio::signal::unix::signal(SignalKind::terminate()) + .expect("failed to listen for interrupt signal"); + let mut sigint = tokio::signal::unix::signal(SignalKind::interrupt()) + .expect("failed to listen for interrupt signal"); + let sigterm = sigterm.recv(); + let sigint = sigint.recv(); + futures::pin_mut!(sigterm, sigint); + futures::future::select(sigterm, sigint).await; + }; + + #[cfg(windows)] + let signal = async move { + // todo(windows): + // `ctrl_close` does not work well, because tokio's signal handler always returns soon, + // but system termiates the application soon after returning CTRL+CLOSE handler. + // So we should implement blocking handler to treat CTRL+CLOSE signal. + let mut ctrl_break = tokio::signal::windows::ctrl_break() + .expect("failed to listen for interrupt signal"); + let mut ctrl_c = tokio::signal::windows::ctrl_c() + .expect("failed to listen for interrupt signal"); + let ctrl_break = ctrl_break.recv(); + let ctrl_c = ctrl_c.recv(); + futures::pin_mut!(ctrl_break, ctrl_c); + futures::future::select(ctrl_break, ctrl_c).await; + }; + axum::Server::from_tcp(listener) .map_err(|e| anyhow!(e))? .serve(app.into_make_service_with_connect_info::()) .with_graceful_shutdown(async move { - let mut sigterm = tokio::signal::unix::signal(SignalKind::terminate()) - .expect("failed to listen for interrupt signal"); - let mut sigint = tokio::signal::unix::signal(SignalKind::interrupt()) - .expect("failed to listen for interrupt signal"); - let sigterm = sigterm.recv(); - let sigint = sigint.recv(); - futures::pin_mut!(sigterm, sigint); - futures::future::select(sigterm, sigint).await; + signal.await; tracing::info!("Received interrupt signal"); if let Some(rpc_server) = rpc_server { @@ -157,10 +177,6 @@ async fn main() -> Result<()> { }) .await .map_err(|e| anyhow!(e))?; - - // todo("windows") - #[cfg(windows)] - unimplemented!(); } _ => { Err(anyhow!(