rpc: close SCGI task on EPIPE to stop event_write() busy-loop

When an SCGI client closes the connection before rtorrent finishes sending
the response, send() in SCgiTask::event_write() returns -1 with errno EPIPE.
EPIPE was grouped with EAGAIN/EINTR as a non-fatal retry-later condition, so
the task was not closed and its descriptor stayed registered for EPOLLOUT. A
broken socket is reported writable immediately, so epoll_wait() returns it on
every iteration and the SCGI thread spins at 100% CPU on one core
indefinitely. The dead connection fd is also leaked (stays ESTAB).

EPIPE is terminal here, not retryable: the peer is gone and the response can
never be delivered. Close the task on EPIPE, matching event_read(), which
already closes on any recv() error other than EAGAIN/EINTR.

Reproduction: open the SCGI socket, send a complete RPC request, then
shutdown(SHUT_RDWR)/close before reading the reply. Stock: the rtorrent-scgi
thread goes to 100% CPU and the connection leaks. With this change: CPU stays
at 0% and the descriptor is closed.
This commit is contained in:
Xirvik Support
2026-06-04 02:27:45 +00:00
committed by Jari Sundell
parent cc15e9308a
commit 49625ab5e5
+1 -1
View File
@@ -184,7 +184,7 @@ SCgiTask::event_write() {
int bytes = ::send(m_fileDesc, m_buffer.data() + m_position, m_buffer.size() - m_position, 0);
if (bytes == -1) {
if (!(errno == EAGAIN || errno == EINTR || errno == EPIPE))
if (!(errno == EAGAIN || errno == EINTR))
close();
return;