On Wed, 20 May 2026 23:08:50 +1000
David Gibson
There are two ways we can tell one of our sockets has received a FIN. We can either see an EPOLLRDHUP epoll event, or we can get a zero-length read (EOF) on the socket. We currently use both, in a mildly confusing way: we only set the FIN_RCVD() flag based on the EPOLLRDHUP event, but then some other close out logic is based on seeing an EOF.
Simplify this by setting the flag based on only the EOF. To make sure we don't miss an event if we get an EPOLLRDHUP with no data, we trigger the forwarding path for EPOLLRDHUP as well as EPOLLIN.
Signed-off-by: David Gibson
--- tcp_splice.c | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/tcp_splice.c b/tcp_splice.c index 8fbd490f..b45f0060 100644 --- a/tcp_splice.c +++ b/tcp_splice.c @@ -487,7 +487,6 @@ static int tcp_splice_forward(struct ctx *c, struct uint8_t lowat_set_flag = RCVLOWAT_SET(fromsidei); uint8_t lowat_act_flag = RCVLOWAT_ACT(fromsidei); int never_read = 1; - int eof = 0;
while (1) { ssize_t readlen, written; @@ -510,7 +509,7 @@ retry: flow_trace(conn, "%zi from read-side call", readlen);
if (!readlen) { - eof = 1; + conn_event(conn, FIN_RCVD(fromsidei));
I'm not sure if I really found a concrete issue with this, but it looks a bit scary, because it changes the semantics of FIN_RCVD, which used to mean that we infer we received a FIN, regardless of whether we're done processing all data from that half of the connection. Now FIN_RCVD is only set if we actually processed all the data and we hit the end of file. The (potential) issue I see here is that we get EPOLLRDHUP, splice() returns -1 with EAGAIN in errno because we had no room in the pipe, and it would have returned 0 instead. Will we ever get our zero-sized "read" later? If not, we might have missed EPOLLRDHUP *and* the end of file. I'm not entirely sure we have guarantees in that sense from splice(). The existing implementation distinguishes between end-of-file we hit in a given iteration, and EPOLLRDHUP we might have seen at any time. That was actually intended. -- Stefano