fix: drive inbound peer connections non-blocking so downloads don't stall
A peer actor multiplexes socket reads with its mailbox on one thread: tick() reads the socket while outgoing messages (e.g. a queued QueueUpload that starts a download) are delivered through the mailbox between ticks. Inbound connections accepted by the listener were left in blocking mode, so once such a peer went idle tick() parked inside read() and never drained the mailbox — a download queued against that peer never sent its QueueUpload and hung. Outbound connections already set non-blocking; do the same for inbound P connections. Covered by a new server-optional e2e test that downloads a file end to end from an in-process mock peer over real P (control) and F (transfer) connections, asserting the bytes written match the source. The mock speaks the library's own public Message wire format, so no dependencies are added.
This commit is contained in:
@@ -115,6 +115,18 @@ fn handle_peer_connection(
|
||||
_peer_ip: &str,
|
||||
_peer_port: u16,
|
||||
) {
|
||||
// The peer actor multiplexes socket reads with its mailbox on a single
|
||||
// thread: `tick()` reads the socket, but outgoing messages (e.g. a queued
|
||||
// QueueUpload for a download) are delivered through the mailbox between
|
||||
// ticks. A blocking socket would park `tick()` inside `read` whenever the
|
||||
// peer is idle, starving the mailbox and stalling downloads. Match the
|
||||
// outbound path and drive this connection non-blocking.
|
||||
if let Err(e) = stream.set_nonblocking(true) {
|
||||
error!("[listener] failed to set peer stream non-blocking: {}", e);
|
||||
return;
|
||||
}
|
||||
stream.set_nodelay(true).ok();
|
||||
|
||||
let client_context = match context.client_context.read_safe() {
|
||||
Ok(c) => c,
|
||||
Err(e) => {
|
||||
|
||||
Reference in New Issue
Block a user