Skip to content

Commit 3ee86fd

Browse files
authored
Add signal handler and shutdown hook (#54)
When the application is running in a container, it is given PID 1 which means it does not automatically get given signal handlers and can't be killed. When running the container in the foreground this stops Ctrl-C from interrupting it while in kubernetes it means the graceful shutdown always times out and the container ends up being forcibly deleted, killing the process. Adding an explicit handler for the common signals used to interrupt processes means that Ctrl-C, kubernetes and `podman stop` all work as expected.
1 parent 8b334be commit 3ee86fd

File tree

1 file changed

+17
-1
lines changed

1 file changed

+17
-1
lines changed

src/main.rs

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@ mod model;
1515
mod test_utils;
1616

1717
use cli::{Cli, Commands};
18+
use tokio::select;
19+
use tokio::signal::unix::{SignalKind, signal};
1820
use tracing::info;
1921

2022
use crate::clients::TiledClient;
@@ -65,5 +67,19 @@ async fn serve(config: GlazedConfig) -> Result<(), Box<dyn error::Error>> {
6567
let listener = tokio::net::TcpListener::bind(config.bind_address).await?;
6668
info!("Serving glazed at {:?}", config.bind_address);
6769

68-
Ok(axum::serve(listener, app).await?)
70+
Ok(axum::serve(listener, app)
71+
.with_graceful_shutdown(signal_handler())
72+
.await?)
73+
}
74+
75+
async fn signal_handler() {
76+
let mut term = signal(SignalKind::terminate()).expect("Failed to create SIGTERM listener");
77+
let mut int = signal(SignalKind::interrupt()).expect("Failed to create SIGINT listener");
78+
let mut quit = signal(SignalKind::interrupt()).expect("Failed to create SIGQUIT listener");
79+
let sig = select! {
80+
_ = term.recv() => "SIGTERM",
81+
_ = int.recv() => "SIGINT",
82+
_ = quit.recv() => "SIGQUIT",
83+
};
84+
info!("Server interrupted by {sig}");
6985
}

0 commit comments

Comments
 (0)