feat: termination signals support
Diff
src/bin/server.rs | 13 +++++++----
src/core/mod.rs | 4 +--
src/core/signal_manager.rs | 56 +-----------------------------------------------
src/core/signals.rs | 51 +++++++++++++++++++++++++++++++++++++++++++-
4 files changed, 62 insertions(+), 62 deletions(-)
@@ -7,7 +7,7 @@ static ALLOC: jemallocator::Jemalloc = jemallocator::Jemalloc;
extern crate static_web_server;
use structopt::StructOpt;
use tracing::info;
use tracing::warn;
use warp::Filter;
use self::static_web_server::core::*;
@@ -22,11 +22,16 @@ async fn server(opts: config::Options) -> Result {
.recover(rejection::handle_rejection)
.with(warp::trace::request());
info!("listening on http://[{}]:{}", &opts.host, &opts.port);
let host = opts.host.parse::<std::net::IpAddr>()?;
let port = opts.port;
tokio::task::spawn(warp::serve(filters).run((host, port)));
warp::serve(filters).run((host, opts.port)).await;
signals::wait(|sig: signals::Signal| {
let code = signals::as_int(sig);
warn!("Signal {} caught. Server execution exited.", code);
std::process::exit(code)
});
Ok(())
}
@@ -2,9 +2,9 @@ pub mod config;
pub mod helpers;
pub mod logger;
pub mod rejection;
pub mod signal_manager;
pub mod signals;
#[macro_use]
pub mod result;
pub use crate::core::result::*;
pub use result::*;
@@ -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,51 @@
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;
pub use signal::Signal;
pub fn wait<F>(func: F)
where
F: Fn(signal::Signal),
{
let sig_trap = signal::trap::Trap::trap(&[SIGTERM, SIGINT, SIGCHLD]);
for sig in sig_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 => func(sig),
}
}
}
pub fn as_int(sig: signal::Signal) -> i32 {
sig as c_int
}