Summary
On SIGTERM/SIGINT, the Go implementation drains in-flight requests via http.Server.Shutdown with a 30s timeout (go/main.go:92-97). The Rust implementation breaks its accept loops and exits main, which drops the tokio runtime — and with it any in-flight serve_connection tasks, aborting responses mid-flight.
Found during the code review of #27 (which rewrote the Rust shutdown path but preserved this pre-existing behavior — it is not a regression from that PR; the old single-listener code behaved the same way).
Affected implementation(s)
Expected behavior
On shutdown signal:
- Stop accepting new connections (already done).
- Allow in-flight requests to complete, up to a 30s deadline (matching Go).
- Exit after drain or deadline, whichever comes first.
Suggested fix (Rust)
Track connections in a tokio::task::JoinSet (or a counter + notify), and on shutdown call hyper's Connection::graceful_shutdown on active connections, then await the set with tokio::time::timeout(Duration::from_secs(30), ...).
Context
Split out from the review follow-ups on PR #27. Related: #25.
Summary
On SIGTERM/SIGINT, the Go implementation drains in-flight requests via
http.Server.Shutdownwith a 30s timeout (go/main.go:92-97). The Rust implementation breaks its accept loops and exitsmain, which drops the tokio runtime — and with it any in-flightserve_connectiontasks, aborting responses mid-flight.Found during the code review of #27 (which rewrote the Rust shutdown path but preserved this pre-existing behavior — it is not a regression from that PR; the old single-listener code behaved the same way).
Affected implementation(s)
server.close()semantics wait for in-flight requests)Expected behavior
On shutdown signal:
Suggested fix (Rust)
Track connections in a
tokio::task::JoinSet(or a counter + notify), and on shutdown call hyper'sConnection::graceful_shutdownon active connections, then await the set withtokio::time::timeout(Duration::from_secs(30), ...).Context
Split out from the review follow-ups on PR #27. Related: #25.