jerpelea opened a new pull request, #19656:
URL: https://github.com/apache/nuttx/pull/19656
## Summary
tcp_start_monitor() is called from accept() (net/inet/inet_sockif.c) for
each newly accepted connection. When the peer had already closed the
connection before accept() ran, the monitor takes an early-return path so that
any read-ahead data buffered on the connection can still be drained; it returns
OK in that case. accept() (net/socket/accept.c) then marks the new socket
_SF_CONNECTED unconditionally.
If the peer aborts the connection with an RST immediately after the
three-way handshake completes (for example any close with SO_LINGER {1, 0}),
the connection is moved to TCP_CLOSED with no buffered data, yet accept() still
hands back a socket that reports _SS_ISCONNECTED. A subsequent blocking send()
on that socket passes the connected check, registers a send callback and waits
on its semaphore forever: the only TCP_ABORT event was delivered before the
callback existed, and no further ACK, POLL or disconnect event is generated for
a closed connection, so the waiter is never woken.
Any server that writes before reading can hit this; the telnet daemon
(netutils/telnetd) is one example, where the accepted session task blocks in
send() and never completes.
Only return OK from the already-closed path when there is actually
read-ahead data to drain. Otherwise the connection is dead, so fall through to
the -ENOTCONN return: accept() then fails cleanly instead of handing back a
socket wedged on a connection that will never make progress. The
graceful-close-with-pending-data case (the reason the OK path exists) is
preserved by the conn->readahead check.
## Impact
RELEASE
## Testing
CI
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]