refactor: cross-platform ctrl-c signal handling
Diff
.gitignore | 1 +-
Cargo.lock | 70 ++++++++++++++++++++--------------------------------
Cargo.toml | 5 +----
src/lib.rs | 5 +----
src/server.rs | 23 +----------------
src/signal_manager.rs | 56 +------------------------------------------
src/signals.rs | 18 +++++++++++++-
7 files changed, 51 insertions(+), 127 deletions(-)
@@ -16,6 +16,7 @@
**/*.data*
**/*.perf*
**/*.out*
**/*.zst
release
.vscode
TODO
@@ -56,12 +56,6 @@ checksum = "4a72c244c1ff497a746a7e1fb3d14bd08420ecda70c8f25c7112f2781652d787"
[[package]]
name = "cfg-if"
version = "0.1.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822"
[[package]]
name = "cfg-if"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
@@ -121,7 +115,17 @@ version = "1.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "81156fece84ab6a9f2afdb109ce3ae577e42b1228441eded99bd77f627953b1a"
dependencies = [
"cfg-if 1.0.0",
"cfg-if",
]
[[package]]
name = "ctrlc"
version = "3.1.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "232295399409a8b7ae41276757b5a1cc21032848d42bff2352261f958b3ca29a"
dependencies = [
"nix",
"winapi",
]
[[package]]
@@ -139,7 +143,7 @@ version = "1.0.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cd3aec53de10fe96d7d8c565eb17f2c687bb5518a2ec453b5b1252964526abe0"
dependencies = [
"cfg-if 1.0.0",
"cfg-if",
"crc32fast",
"libc",
"miniz_oxide",
@@ -178,7 +182,7 @@ version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7fcd999463524c52659517fe2cea98493cfe485d10565e7b0fb07dbba7ad2753"
dependencies = [
"cfg-if 1.0.0",
"cfg-if",
"libc",
"wasi",
]
@@ -328,9 +332,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
[[package]]
name = "libc"
version = "0.2.97"
version = "0.2.98"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "12b8adadd720df158f4d70dfe7ccc6adb0472d7c55ca83445f6a5ab3e36f8fb6"
checksum = "320cfe77175da3a483efed4bc0adc1968ca050b098ce4f2f1c13a56626128790"
[[package]]
name = "log"
@@ -347,7 +351,7 @@ version = "0.4.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "51b9bbe6c47d51fc3e1a9b945965946b4c44142ab8792c50835a980d362c2710"
dependencies = [
"cfg-if 1.0.0",
"cfg-if",
]
[[package]]
@@ -413,15 +417,14 @@ dependencies = [
[[package]]
name = "nix"
version = "0.14.1"
version = "0.20.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6c722bee1037d430d0f8e687bbdbf222f27cc6e4e68d5caf630857bb2b6dbdce"
checksum = "fa9b4819da1bc61c0ea48b63b7bc8604064dd43013e7cc325df098d49cd7c18a"
dependencies = [
"bitflags",
"cc",
"cfg-if 0.1.10",
"cfg-if",
"libc",
"void",
]
[[package]]
@@ -466,7 +469,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "549430950c79ae24e6d02e0b7404534ecf311d94cc9f861e9e4020187d13d885"
dependencies = [
"bitflags",
"cfg-if 1.0.0",
"cfg-if",
"foreign-types",
"libc",
"once_cell",
@@ -852,16 +855,6 @@ dependencies = [
]
[[package]]
name = "signal"
version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2f6ce83b159ab6984d2419f495134972b48754d13ff2e3f8c998339942b56ed9"
dependencies = [
"libc",
"nix",
]
[[package]]
name = "siphasher"
version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -872,6 +865,7 @@ name = "static-web-server"
version = "1.17.1"
dependencies = [
"chrono",
"ctrlc",
"env_logger",
"flate2",
"humansize",
@@ -884,10 +878,8 @@ dependencies = [
"log 0.4.14",
"mime",
"mime_guess",
"nix",
"openssl",
"percent-encoding 2.1.0",
"signal",
"structopt",
"tempfile",
"time",
@@ -896,9 +888,9 @@ dependencies = [
[[package]]
name = "structopt"
version = "0.3.21"
version = "0.3.22"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5277acd7ee46e63e5168a80734c9f6ee81b1367a7d8772a2d765df2a3705d28c"
checksum = "69b041cdcb67226aca307e6e7be44c8806423d83e018bd662360a93dabce4d71"
dependencies = [
"clap",
"lazy_static",
@@ -907,9 +899,9 @@ dependencies = [
[[package]]
name = "structopt-derive"
version = "0.4.14"
version = "0.4.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5ba9cdfda491b814720b6b06e0cac513d922fc407582032e8706e9f137976f90"
checksum = "7813934aecf5f51a54775e00068c237de98489463968231a51746bbbc03f9c10"
dependencies = [
"heck",
"proc-macro-error",
@@ -935,7 +927,7 @@ version = "3.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dac1c663cfc93810f88aed9b8941d48cabf856a1b111c29a40439018d870eb22"
dependencies = [
"cfg-if 1.0.0",
"cfg-if",
"libc",
"rand 0.8.4",
"redox_syscall",
@@ -1027,9 +1019,9 @@ dependencies = [
[[package]]
name = "unicode-segmentation"
version = "1.7.1"
version = "1.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bb0d2e7be6ae3a5fa87eed5fb451aff96f2573d2694942e40543ae0bbe19c796"
checksum = "8895849a949e7845e06bd6dc1aa51731a103c42707010a5b591c0038fb73385b"
[[package]]
name = "unicode-width"
@@ -1091,12 +1083,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5fecdca9a5291cc2b8dcf7dc02453fee791a280f3743cb0905f8822ae463b3fe"
[[package]]
name = "void"
version = "1.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d"
[[package]]
name = "wasi"
version = "0.10.2+wasi-snapshot-preview1"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -39,11 +39,8 @@ structopt = { version = "0.3", default-features = false }
time = "0.1"
url = "1.4"
percent-encoding = "2.1"
ctrlc = { version = "3.1", features = ["termination"] }
[target.'cfg(not(windows))'.dependencies.nix]
version = "0.14"
[target.'cfg(not(windows))'.dependencies.signal]
version = "0.7"
[target.'cfg(all(target_env = "musl", target_pointer_width = "64"))'.dependencies.jemallocator]
version = "0.3"
@@ -13,10 +13,7 @@ pub mod gzip;
pub mod helpers;
pub mod logger;
pub mod server;
#[cfg(not(windows))]
pub mod signal_manager;
pub mod signals;
pub mod staticfile_middleware;
pub mod staticfiles;
@@ -3,7 +3,7 @@ use iron::{Chain, Iron, Listening};
use crate::staticfile_middleware::HttpToHttpsRedirect;
use crate::staticfiles::*;
use crate::{config::Options, logger};
use crate::{config::Options, logger, signals};
#[derive(Debug)]
@@ -102,24 +102,5 @@ fn on_server_running(server_name: &str, running_servers: &[RunningServer]) {
))
});
handle_signals()
}
#[cfg(not(windows))]
fn handle_signals() {
use crate::signal_manager;
signal_manager::wait_for_signal(|sig: signal::Signal| {
let code = signal_manager::signal_to_int(sig);
println!();
warn!("Signal {} caught. Server execution exited.", code);
std::process::exit(code)
})
}
#[cfg(windows)]
fn handle_signals() {
signals::wait_for_ctrl_c()
}
@@ -1,56 +0,0 @@
use nix::errno::Errno;
use nix::libc::c_int;
use nix::sys::signal::{SIGCHLD, SIGINT, SIGTERM};
use nix::sys::wait::WaitStatus::{Exited, Signaled, StillAlive};
use nix::sys::wait::{waitpid, WaitPidFlag};
use nix::Error;
use signal::trap::Trap;
pub fn wait_for_signal<F>(f: F)
where
F: Fn(signal::Signal),
{
let signal_trap = Trap::trap(&[SIGTERM, SIGINT, SIGCHLD]);
for sig in signal_trap {
match sig {
SIGCHLD => {
loop {
match waitpid(None, Some(WaitPidFlag::WNOHANG)) {
Ok(Exited(pid, status)) => {
println!("{} exited with status {}", pid, status);
continue;
}
Ok(Signaled(pid, sig, _)) => {
println!("{} killed by {}", pid, sig as c_int);
continue;
}
Ok(StillAlive) => {
break;
}
Ok(status) => {
println!("Temporary status {:?}", status);
continue;
}
Err(Error::Sys(Errno::ECHILD)) => {
return;
}
Err(e) => {
panic!("Error {:?}", e);
}
}
}
}
sig => f(sig),
}
}
}
pub fn signal_to_int(sig: signal::Signal) -> i32 {
sig as c_int
}
@@ -0,0 +1,18 @@
use ctrlc;
use std::{process, sync::mpsc::channel};
pub fn wait_for_ctrl_c() {
let (tx, rx) = channel();
ctrlc::set_handler(move || tx.send(()).expect("could not send signal on channel"))
.expect("error setting Ctrl-C handler");
info!("press Ctrl+C to shutdown the server");
rx.recv().expect("could not receive signal from channel");
warn!("Ctrl+C signal caught, shutting down the server execution");
process::exit(1)
}