Skip to content

Commit a876d8c

Browse files
committed
Merge #589: Fix broken grateful shutdown for tracker API
452b4a0 feat: improve http_health_check output (Jose Celano) ac18605 feat: improve log when starting the API (Jose Celano) 53613ec feat: start log lines with capital (Jose Celano) cf613b8 fix: [#588] broken grateful shutdown for tracker API (Jose Celano) Pull request description: The internal halt channel was not working because the sender was being dropped just after starting the server. That also made the `shutdown_signal` fail. ```rust pub async fn shutdown_signal(rx_halt: tokio::sync::oneshot::Receiver<Halted>) { let halt = async { match rx_halt.await { Ok(signal) => signal, Err(err) => panic!("Failed to install stop signal: {err}"), } }; tokio::select! { signal = halt => { info!("Halt signal processed: {}", signal) }, () = global_shutdown_signal() => { info!("Global shutdown signal processed") } } } ``` Since the signal branch in the `tokio::select!` was finishing the global_shutdown_signal did not work either. So you had to kill the process manually to stop the tracker. It seems Rust partially dropped the `Running::halt_taks` attribute and that closed the channel. The issue was introduced in this commit: 13140f6 ACKs for top commit: josecelano: ACK 452b4a0 Tree-SHA512: 96afc18a62c55b1bd5a97e97f43bd0c2603de00944211c46197944b2e24008f54e4d7c96b43b237e029c61e67f060716315f85433abcb3234ba880d1e20032e3
2 parents 5f6eed7 + 452b4a0 commit a876d8c

File tree

7 files changed

+37
-18
lines changed

7 files changed

+37
-18
lines changed

src/bin/http_health_check.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ async fn main() {
1111
let args: Vec<String> = env::args().collect();
1212
if args.len() != 2 {
1313
eprintln!("Usage: cargo run --bin http_health_check <HEALTH_URL>");
14-
eprintln!("Example: cargo run --bin http_health_check http://127.0.0.1:1212/api/health_check");
14+
eprintln!("Example: cargo run --bin http_health_check http://127.0.0.1:1313/health_check");
1515
std::process::exit(1);
1616
}
1717

src/bootstrap/jobs/health_check_api.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ pub async fn start_job(config: Arc<Configuration>) -> JoinHandle<()> {
5555

5656
// Wait until the API server job is running
5757
match rx_start.await {
58-
Ok(msg) => info!("Torrust Health Check API server started on socket: {}", msg.address),
58+
Ok(msg) => info!("Torrust Health Check API server started on: http://{}", msg.address),
5959
Err(e) => panic!("the Health Check API server was dropped: {e}"),
6060
}
6161

src/bootstrap/jobs/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ pub struct Started {
2222

2323
pub async fn make_rust_tls(enabled: bool, cert: &Option<String>, key: &Option<String>) -> Option<Result<RustlsConfig, Error>> {
2424
if !enabled {
25-
info!("tls not enabled");
25+
info!("TLS not enabled");
2626
return None;
2727
}
2828

src/bootstrap/jobs/tracker_apis.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@ async fn start_v1(socket: SocketAddr, tls: Option<RustlsConfig>, tracker: Arc<co
8080
.expect("it should be able to start to the tracker api");
8181

8282
tokio::spawn(async move {
83+
assert!(!server.state.halt_task.is_closed(), "Halt channel should be open");
8384
server.state.task.await.expect("failed to close service");
8485
})
8586
}

src/servers/apis/server.rs

Lines changed: 23 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ use axum_server::tls_rustls::RustlsConfig;
3030
use axum_server::Handle;
3131
use derive_more::Constructor;
3232
use futures::future::BoxFuture;
33+
use log::{error, info};
3334
use tokio::sync::oneshot::{Receiver, Sender};
3435

3536
use super::routes::router;
@@ -101,13 +102,22 @@ impl ApiServer<Stopped> {
101102
launcher
102103
});
103104

104-
Ok(ApiServer {
105-
state: Running {
106-
binding: rx_start.await.expect("unable to start service").address,
107-
halt_task: tx_halt,
108-
task,
105+
let api_server = match rx_start.await {
106+
Ok(started) => ApiServer {
107+
state: Running {
108+
binding: started.address,
109+
halt_task: tx_halt,
110+
task,
111+
},
109112
},
110-
})
113+
Err(err) => {
114+
let msg = format!("Unable to start API server: {err}");
115+
error!("{}", msg);
116+
panic!("{}", msg);
117+
}
118+
};
119+
120+
Ok(api_server)
111121
}
112122
}
113123

@@ -159,29 +169,32 @@ impl Launcher {
159169
tokio::task::spawn(graceful_shutdown(
160170
handle.clone(),
161171
rx_halt,
162-
format!("shutting down http server on socket address: {address}"),
172+
format!("Shutting down tracker API server on socket address: {address}"),
163173
));
164174

165175
let tls = self.tls.clone();
176+
let protocol = if tls.is_some() { "https" } else { "http" };
166177

167178
let running = Box::pin(async {
168179
match tls {
169180
Some(tls) => axum_server::from_tcp_rustls(socket, tls)
170181
.handle(handle)
171182
.serve(router.into_make_service_with_connect_info::<std::net::SocketAddr>())
172183
.await
173-
.expect("Axum server crashed."),
184+
.expect("Axum server for tracker API crashed."),
174185
None => axum_server::from_tcp(socket)
175186
.handle(handle)
176187
.serve(router.into_make_service_with_connect_info::<std::net::SocketAddr>())
177188
.await
178-
.expect("Axum server crashed."),
189+
.expect("Axum server for tracker API crashed."),
179190
}
180191
});
181192

193+
info!(target: "API", "API server started on {protocol}://{}", address);
194+
182195
tx_start
183196
.send(Started { address })
184-
.expect("the HTTP(s) Tracker service should not be dropped");
197+
.expect("the HTTP(s) Tracker API service should not be dropped");
185198

186199
running
187200
}

src/servers/http/server.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ impl Launcher {
4747
tokio::task::spawn(graceful_shutdown(
4848
handle.clone(),
4949
rx_halt,
50-
format!("shutting down http server on socket address: {address}"),
50+
format!("Shutting down http server on socket address: {address}"),
5151
));
5252

5353
let tls = self.tls.clone();

src/servers/signals.rs

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -46,11 +46,16 @@ pub async fn global_shutdown_signal() {
4646
///
4747
/// Will panic if the `stop_receiver` resolves with an error.
4848
pub async fn shutdown_signal(rx_halt: tokio::sync::oneshot::Receiver<Halted>) {
49-
let halt = async { rx_halt.await.expect("Failed to install stop signal.") };
49+
let halt = async {
50+
match rx_halt.await {
51+
Ok(signal) => signal,
52+
Err(err) => panic!("Failed to install stop signal: {err}"),
53+
}
54+
};
5055

5156
tokio::select! {
52-
_ = halt => {},
53-
() = global_shutdown_signal() => {}
57+
signal = halt => { info!("Halt signal processed: {}", signal) },
58+
() = global_shutdown_signal() => { info!("Global shutdown signal processed") }
5459
}
5560
}
5661

@@ -64,7 +69,7 @@ pub async fn shutdown_signal_with_message(rx_halt: tokio::sync::oneshot::Receive
6469
pub async fn graceful_shutdown(handle: axum_server::Handle, rx_halt: tokio::sync::oneshot::Receiver<Halted>, message: String) {
6570
shutdown_signal_with_message(rx_halt, message).await;
6671

67-
info!("sending graceful shutdown signal");
72+
info!("Sending graceful shutdown signal");
6873
handle.graceful_shutdown(Some(Duration::from_secs(90)));
6974

7075
println!("!! shuting down in 90 seconds !!");

0 commit comments

Comments
 (0)