Line data Source code
1 : use std::convert::Infallible;
2 :
3 : use anyhow::bail;
4 : use tokio_util::sync::CancellationToken;
5 : use tracing::{info, warn};
6 :
7 : use crate::metrics::{Metrics, ServiceInfo};
8 :
9 : /// Handle unix signals appropriately.
10 0 : pub async fn handle<F>(
11 0 : token: CancellationToken,
12 0 : mut refresh_config: F,
13 0 : ) -> anyhow::Result<Infallible>
14 0 : where
15 0 : F: FnMut(),
16 0 : {
17 : use tokio::signal::unix::{SignalKind, signal};
18 :
19 0 : let mut hangup = signal(SignalKind::hangup())?;
20 0 : let mut interrupt = signal(SignalKind::interrupt())?;
21 0 : let mut terminate = signal(SignalKind::terminate())?;
22 :
23 : loop {
24 0 : tokio::select! {
25 : // Hangup is commonly used for config reload.
26 0 : _ = hangup.recv() => {
27 0 : info!("received SIGHUP");
28 0 : refresh_config();
29 : }
30 : // Shut down the whole application.
31 0 : _ = interrupt.recv() => {
32 0 : warn!("received SIGINT, exiting immediately");
33 0 : Metrics::get().service.info.set_label(ServiceInfo::terminating());
34 0 : bail!("interrupted");
35 : }
36 0 : _ = terminate.recv() => {
37 0 : warn!("received SIGTERM, shutting down once all existing connections have closed");
38 0 : Metrics::get().service.info.set_label(ServiceInfo::terminating());
39 0 : token.cancel();
40 : }
41 : }
42 : }
43 0 : }
|