From b08b7bf1c422e70d927cabff7b2403975f43e5f5 Mon Sep 17 00:00:00 2001 From: Renaud Allard Date: Wed, 18 Mar 2026 15:59:36 +0100 Subject: [PATCH] Fix infinite loop in post-relay flush when peer stops reading write_buffer() returns 0 on EAGAIN/EWOULDBLOCK (from SO_SNDTIMEO timeout), but the flush loops after relay_connection() only broke on return < 0. This caused an infinite retry loop when the peer stopped accepting data: send() would block for idletimeout seconds, return EAGAIN, write_buffer would return 0, and the loop would retry forever. Each stuck thread consumes a maxclients slot. Once all slots are exhausted, the proxy stops accepting new connections entirely. Fix: break on write_buffer() <= 0 in both client and server flush loops. These are best-effort flushes after the main relay loop already delivered the bulk of the data. --- src/reqs.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/reqs.c b/src/reqs.c index 94ce7673..695d48f2 100644 --- a/src/reqs.c +++ b/src/reqs.c @@ -1261,7 +1261,7 @@ static void relay_connection (struct conn_s *connptr) } while (buffer_size (connptr->sbuffer) > 0) { - if (write_buffer (connptr->client_fd, connptr->sbuffer) < 0) + if (write_buffer (connptr->client_fd, connptr->sbuffer) <= 0) break; } shutdown (connptr->client_fd, SHUT_WR); @@ -1278,7 +1278,7 @@ static void relay_connection (struct conn_s *connptr) } while (buffer_size (connptr->cbuffer) > 0) { - if (write_buffer (connptr->server_fd, connptr->cbuffer) < 0) + if (write_buffer (connptr->server_fd, connptr->cbuffer) <= 0) break; }