Skip to content

Commit e24c18f

Browse files
authored
Merge pull request #139 from chrivers/chrivers/sigterm-handling
Since Bifrost is running as pid 1 in docker, we need to catch SIGTERM to perform clean shutdowns without waiting for docker timeout to stop the container. For example, this makes the "stop" button in Home Assistant react quickly, and perform a clean shutdown.
2 parents 70895fc + e511f21 commit e24c18f

File tree

1 file changed

+30
-7
lines changed

1 file changed

+30
-7
lines changed

src/main.rs

Lines changed: 30 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,10 @@ use bifrost::server::http::HttpServer;
88
use bifrost::server::mdns::MdnsService;
99
use bifrost::server::{self, Protocol};
1010
use svc::manager::ServiceManager;
11+
use svc::manager::SvmClient;
1112
use svc::serviceid::ServiceId;
13+
use tokio::signal;
14+
use tokio::signal::unix::SignalKind;
1215

1316
/*
1417
* Formatter function to output in syslog format. This makes sense when running
@@ -129,6 +132,31 @@ async fn build_tasks(appstate: &AppState) -> ApiResult<()> {
129132
Ok(())
130133
}
131134

135+
fn install_signal_handlers(appstate: &AppState) -> ApiResult<()> {
136+
async fn shutdown(msg: &str, mut mgr: SvmClient) {
137+
log::warn!("{msg}");
138+
let _ = std::io::stderr().flush();
139+
let _ = mgr.shutdown().await;
140+
}
141+
142+
let mgr = appstate.manager();
143+
tokio::spawn(async move {
144+
if matches!(signal::ctrl_c().await, Ok(())) {
145+
shutdown("Ctrl-C pressed, exiting..", mgr).await;
146+
}
147+
});
148+
149+
let mgr = appstate.manager();
150+
let mut signal = signal::unix::signal(SignalKind::terminate())?;
151+
tokio::spawn(async move {
152+
if matches!(signal.recv().await, Some(())) {
153+
shutdown("SIGTERM received, exiting..", mgr).await;
154+
}
155+
});
156+
157+
Ok(())
158+
}
159+
132160
async fn run() -> ApiResult<()> {
133161
init_logging()?;
134162

@@ -142,14 +170,9 @@ async fn run() -> ApiResult<()> {
142170

143171
let appstate = AppState::from_config(config, client).await?;
144172

145-
build_tasks(&appstate).await?;
173+
install_signal_handlers(&appstate)?;
146174

147-
tokio::spawn(async move {
148-
if matches!(tokio::signal::ctrl_c().await, Ok(())) {
149-
log::warn!("Ctrl-C pressed, exiting..");
150-
let _ = appstate.manager().shutdown().await;
151-
}
152-
});
175+
build_tasks(&appstate).await?;
153176

154177
future.await??;
155178

0 commit comments

Comments
 (0)