fix(daemon): ask the OS for enough open files, and stop spinning when it says no

A search fans out to hundreds of peers, each holding a socket. A shell hands
its children a soft limit of 256 open files on macOS, which one busy search
blows straight through; a one-shot command never noticed because it exited
before it mattered, but a resident daemon hits it and then cannot accept peers
or control connections. From a client that looks like 'cannot reach the
daemon: Connection closed', intermittently, for no visible reason.

The daemon now raises its own soft limit to 8192 at startup, before anything
opens a socket, and says so plainly when the hard limit will not allow it.
macOS rejects an unlimited hard limit for open files, so both fields are named.

Both accept loops also slept zero on failure. Out of descriptors does not clear
by the next instruction, so one exhausted moment became a spinning core and
thousands of identical log lines — which is what the report looked like. They
now back off.
This commit is contained in:
Michel de Graaf
2026-07-27 20:16:41 +02:00
parent 4836934881
commit 220beb4e41
5 changed files with 104 additions and 3 deletions
+9 -1
View File
@@ -38,6 +38,9 @@ const MAX_LINE: u64 = 1 << 20;
/// connection open for events without sending anything.
const AUTH_TIMEOUT: Duration = Duration::from_secs(30);
/// How long to wait before accepting again after a failure.
const ACCEPT_BACKOFF: Duration = Duration::from_millis(100);
/// How many control connections may be open at once. Far above any real use
/// (a TUI, a few scripts, an agent), and low enough that an unauthenticated
/// peer cannot exhaust the daemon's threads.
@@ -132,7 +135,12 @@ impl Listener {
loop {
match self.accept() {
Ok(stream) => spawn_connection(stream, Arc::clone(&daemon)),
Err(e) => soulseek_rs::warn!("control accept failed: {e}"),
Err(e) => {
soulseek_rs::warn!("control accept failed: {e}");
// Out of file descriptors does not clear by the next
// instruction; retrying flat out spins a core.
std::thread::sleep(ACCEPT_BACKOFF);
}
}
}
}