Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions crates/fbuild-daemon/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -407,6 +407,17 @@ fn is_pid_alive(pid: u32) -> bool {
/// so it's safe there but not on Windows). See ISSUES.md "Issue B5a".
/// * **Unix** — sets `SO_REUSEADDR`, which only permits `TIME_WAIT`
/// recovery on this OS family.
/// * **All platforms** — sets `SO_LINGER = 0` on the listening socket so
/// that accepted client sockets inherit a zero linger and force an
/// immediate `RST` on close instead of going through the
/// `FIN / CLOSE_WAIT / TIME_WAIT` dance. After a hard-kill of the
/// daemon, this prevents the kernel from leaking dangling `CLOSE_WAIT`
/// state on client sockets that outlives the daemon itself and would
/// otherwise block a fresh instance from re-binding the port. SO_LINGER
/// is inherited from the listener by `accept(2)` on Linux, macOS, and
/// Windows (AFD.sys), so setting it once on the listener covers every
/// subsequently accepted connection without needing to hook axum 0.7's
/// internal accept loop. See FastLED/fbuild#32.
///
/// Bind is retried up to 3 times with 500 ms backoff to handle the brief
/// window where a hard-killed previous instance still has kernel TCP
Expand Down Expand Up @@ -443,6 +454,13 @@ fn bind_listener_with_retry(addr: &str) -> tokio::net::TcpListener {
}
}

// Force RST on close for accepted client sockets — inherited via
// `accept(2)` on Linux/macOS/Windows. See doc comment above and
// FastLED/fbuild#32.
if let Err(e) = sock.set_linger(Some(std::time::Duration::ZERO)) {
tracing::warn!("failed to set SO_LINGER=0 on listener: {}", e);
}

if let Err(e) = sock.set_nonblocking(true) {
eprintln!("failed to set non-blocking: {}", e);
std::process::exit(1);
Expand Down
Loading