mirror of
https://github.com/rakshasa/rtorrent.git
synced 2026-10-04 21:29:21 +00:00
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:
committed by
Jari Sundell
parent
cc15e9308a
commit
49625ab5e5
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user