From c16e7d50e5e0623d19be2621c4ab78d2db1023f6 Mon Sep 17 00:00:00 2001 From: Jose Quintana Date: Sat, 30 Oct 2021 00:46:53 +0200 Subject: [PATCH] refactor: explicit `ctrl+c` signal handling for windows it preserves `graceful shutdown` but via `ctrl+c` --- Cargo.lock | 2 ++ Cargo.toml | 2 +- src/server.rs | 27 ++++++++++++++++++++++----- src/signals.rs | 26 +++++++++++--------------- 4 files changed, 36 insertions(+), 21 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index ac8840e..0d0b2f4 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -986,7 +986,9 @@ dependencies = [ "memchr", "mio", "num_cpus", + "once_cell", "pin-project-lite", + "signal-hook-registry", "tokio-macros", "winapi", ] diff --git a/Cargo.toml b/Cargo.toml index 5dd381b..273dbba 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -44,7 +44,7 @@ percent-encoding = "2.1" pin-project = "1.0" structopt = { version = "0.3", default-features = false } time = "0.1" -tokio = { version = "1", features = ["rt-multi-thread", "macros", "fs", "io-util"], default-features = false } +tokio = { version = "1", features = ["rt-multi-thread", "macros", "fs", "io-util", "signal"], default-features = false } tokio-rustls = { version = "0.22" } tokio-util = { version = "0.6", features = ["io"] } tracing = "0.1" diff --git a/src/server.rs b/src/server.rs index 7b268ec..191b3eb 100644 --- a/src/server.rs +++ b/src/server.rs @@ -156,12 +156,18 @@ impl Server { "error during TLS server initialization, probably cert or key file missing", ); + #[cfg(not(windows))] let signals = signals::create_signals()?; + #[cfg(not(windows))] let handle = signals.handle(); - let server = HyperServer::builder(TlsAcceptor::new(tls, incoming)) - .serve(router_service) - .with_graceful_shutdown(signals::wait_for_signals(signals)); + let server = + HyperServer::builder(TlsAcceptor::new(tls, incoming)).serve(router_service); + + #[cfg(not(windows))] + let server = server.with_graceful_shutdown(signals::wait_for_signals(signals)); + #[cfg(windows)] + let server = server.with_graceful_shutdown(signals::wait_for_ctrl_c()); tracing::info!( parent: tracing::info_span!("Server::start_server", ?addr_str, ?threads), @@ -172,17 +178,26 @@ impl Server { tracing::info!("press ctrl+c to shut down the server"); server.await?; + + #[cfg(not(windows))] handle.close(); } else { // HTTP/1 + + #[cfg(not(windows))] let signals = signals::create_signals()?; + #[cfg(not(windows))] let handle = signals.handle(); let server = HyperServer::from_tcp(tcp_listener) .unwrap() .tcp_nodelay(true) - .serve(router_service) - .with_graceful_shutdown(signals::wait_for_signals(signals)); + .serve(router_service); + + #[cfg(not(windows))] + let server = server.with_graceful_shutdown(signals::wait_for_signals(signals)); + #[cfg(windows)] + let server = server.with_graceful_shutdown(signals::wait_for_ctrl_c()); tracing::info!( parent: tracing::info_span!("Server::start_server", ?addr_str, ?threads), @@ -193,6 +208,8 @@ impl Server { tracing::info!("press ctrl+c to shut down the server"); server.await?; + + #[cfg(not(windows))] handle.close(); } diff --git a/src/signals.rs b/src/signals.rs index 2cbc9f8..20fc4da 100644 --- a/src/signals.rs +++ b/src/signals.rs @@ -1,10 +1,8 @@ #[cfg(not(windows))] -use {futures_util::stream::StreamExt, signal_hook::consts::signal::*, signal_hook_tokio::Signals}; - -#[cfg(windows)] -type Signals = futures_util::stream::Empty<()>; - -use crate::Result; +use { + crate::Result, futures_util::stream::StreamExt, signal_hook::consts::signal::*, + signal_hook_tokio::Signals, +}; #[cfg(not(windows))] /// It creates a common list of signals stream for `SIGTERM`, `SIGINT` and `SIGQUIT` to be observed. @@ -12,14 +10,8 @@ pub fn create_signals() -> Result { Ok(Signals::new(&[SIGHUP, SIGTERM, SIGINT, SIGQUIT])?) } -#[cfg(windows)] -// No signal handling available on Windows for now -pub fn create_signals() -> Result { - Ok(futures_util::stream::empty()) -} - #[cfg(not(windows))] -/// It waits for a specific type of incoming signals. +/// It waits for a specific type of incoming signals included `ctrl+c`. pub async fn wait_for_signals(signals: Signals) { let mut signals = signals.fuse(); while let Some(signal) = signals.next().await { @@ -38,5 +30,9 @@ pub async fn wait_for_signals(signals: Signals) { } #[cfg(windows)] -// No signal handling available on Windows for now -pub async fn wait_for_signals(signals: Signals) {} +/// It waits for an incoming `ctrl+c` signal on Windows. +pub async fn wait_for_ctrl_c() { + tokio::signal::ctrl_c() + .await + .expect("failed to install ctrl+c signal handler"); +} -- libgit2 1.7.2