index : static-web-server.git

ascending towards madness

author Jose Quintana <joseluisquintana20@gmail.com> 2021-10-29 10:31:22.0 +00:00:00
committer Jose Quintana <joseluisquintana20@gmail.com> 2021-10-29 10:31:22.0 +00:00:00
commit
4a91844cc671b55b40151ce2f639037a8cb90902 [patch]
tree
7749db88f71b35a49058ebf8cf57f50a6bc50456
parent
beb009b2dc4673c661ea1fb8d85ad4ee58c94ff6
download
4a91844cc671b55b40151ce2f639037a8cb90902.tar.gz

refactor: proper SIGTERM, SIGINT and SIGQUIT handling



Diff

 Cargo.lock     | 27 +++++++++++++++++++++++++--
 Cargo.toml     |  4 +++-
 src/server.rs  | 17 ++++++++++++-----
 src/signals.rs | 34 +++++++++++++++++++++++++++-------
 4 files changed, 67 insertions(+), 15 deletions(-)

diff --git a/Cargo.lock b/Cargo.lock
index b929e4e..ac8840e 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -822,6 +822,17 @@ dependencies = [
]

[[package]]
name = "signal-hook"
version = "0.3.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c98891d737e271a2954825ef19e46bd16bdb98e2746f2eec4f7a4ef7946efd1"
dependencies = [
 "cc",
 "libc",
 "signal-hook-registry",
]

[[package]]
name = "signal-hook-registry"
version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -831,6 +842,18 @@ dependencies = [
]

[[package]]
name = "signal-hook-tokio"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f6c5d32165ff8b94e68e7b3bdecb1b082e958c22434b363482cfb89dcd6f3ff8"
dependencies = [
 "futures-core",
 "libc",
 "signal-hook",
 "tokio",
]

[[package]]
name = "slab"
version = "0.4.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -877,6 +900,8 @@ dependencies = [
 "num_cpus",
 "percent-encoding",
 "pin-project",
 "signal-hook",
 "signal-hook-tokio",
 "structopt",
 "time",
 "tokio",
@@ -961,9 +986,7 @@ 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 e238a43..d49f90d 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -44,11 +44,13 @@ 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", "signal"], default-features = false }
tokio = { version = "1", features = ["rt-multi-thread", "macros", "fs", "io-util"], default-features = false }
tokio-rustls = { version = "0.22" }
tokio-util = { version = "0.6", features = ["io"] }
tracing = "0.1"
tracing-subscriber = "0.2"
signal-hook = { version = "0.3.4", features = ["extended-siginfo"] }
signal-hook-tokio = { version = "0.3", features = ["futures-v0_3"], default-features = false }

[target.'cfg(all(target_env = "musl", target_pointer_width = "64"))'.dependencies.jemallocator]
version = "0.3"
diff --git a/src/server.rs b/src/server.rs
index 2d50dee..7b268ec 100644
--- a/src/server.rs
+++ b/src/server.rs
@@ -156,9 +156,12 @@ impl Server {
                    "error during TLS server initialization, probably cert or key file missing",
                );

            let signals = signals::create_signals()?;
            let handle = signals.handle();

            let server = HyperServer::builder(TlsAcceptor::new(tls, incoming))
                .serve(router_service)
                .with_graceful_shutdown(signals::wait_for_ctrl_c());
                .with_graceful_shutdown(signals::wait_for_signals(signals));

            tracing::info!(
                parent: tracing::info_span!("Server::start_server", ?addr_str, ?threads),
@@ -166,17 +169,20 @@ impl Server {
                addr_str
            );

            tracing::info!("press Ctrl + C to shut down the server");
            tracing::info!("press ctrl+c to shut down the server");

            server.await?;
            handle.close();
        } else {
            // HTTP/1
            let signals = signals::create_signals()?;
            let handle = signals.handle();

            let server = HyperServer::from_tcp(tcp_listener)
                .unwrap()
                .tcp_nodelay(true)
                .serve(router_service)
                .with_graceful_shutdown(signals::wait_for_ctrl_c());
                .with_graceful_shutdown(signals::wait_for_signals(signals));

            tracing::info!(
                parent: tracing::info_span!("Server::start_server", ?addr_str, ?threads),
@@ -184,12 +190,13 @@ impl Server {
                addr_str
            );

            tracing::info!("press Ctrl + C to shut down the server");
            tracing::info!("press ctrl+c to shut down the server");

            server.await?;
            handle.close();
        }

        tracing::warn!("Ctrl+C signal caught, shutting down the server execution");
        tracing::warn!("termination signal caught, shutting down the server execution");

        Ok(())
    }
diff --git a/src/signals.rs b/src/signals.rs
index 2130315..0fe03d0 100644
--- a/src/signals.rs
+++ b/src/signals.rs
@@ -1,8 +1,28 @@
/// It waits for a `Ctrl-C` incoming signal.
pub async fn wait_for_ctrl_c() {
    tracing::debug!("server waiting for incoming Ctrl+C signals");
    tokio::signal::ctrl_c()
        .await
        .expect("failed to install the Ctrl+C signal handler");
    tracing::debug!("server caught an incoming Ctrl+C signal, starting graceful shutdown");
use futures_util::stream::StreamExt;
use signal_hook::consts::signal::*;
use signal_hook_tokio::Signals;

use crate::Result;

/// It creates a common list of signals stream for `SIGTERM`, `SIGINT` and `SIGQUIT` to be observed.
pub fn create_signals() -> Result<Signals> {
    Ok(Signals::new(&[SIGHUP, SIGTERM, SIGINT, SIGQUIT])?)
}

/// It waits for a specific type of incoming signals.
pub async fn wait_for_signals(signals: Signals) {
    let mut signals = signals.fuse();
    while let Some(signal) = signals.next().await {
        match signal {
            SIGHUP => {
                // Note: for now we don't do something for SIGHUPs
                tracing::debug!("SIGHUP caught, nothing to do about")
            }
            SIGTERM | SIGINT | SIGQUIT => {
                tracing::debug!("an incoming SIGTERM received, SIGINT or SIGQUIT signal, delegating graceful shutdown to server");
                break;
            }
            _ => unreachable!(),
        }
    }
}