public inbox for passt-dev@passt.top
 help / color / mirror / code / Atom feed
From: David Gibson <david@gibson.dropbear.id.au>
To: passt-dev@passt.top, Stefano Brivio <sbrivio@redhat.com>
Cc: Paul Holzinger <pholzing@redhat.com>,
	David Gibson <david@gibson.dropbear.id.au>
Subject: [PATCH 2/6] tcp_splice: Avoid missing EOF recognition while forwarding
Date: Wed, 20 May 2026 23:08:47 +1000	[thread overview]
Message-ID: <20260520130851.436931-3-david@gibson.dropbear.id.au> (raw)
In-Reply-To: <20260520130851.436931-1-david@gibson.dropbear.id.au>

tcp_splice_sock_handler() has an optimised path for the common case where
the amount we splice(2) into the pipe is exactly the same as the amount we
splice(2) out again.  If the pipe is empty at that point, we stop
forwarding until we get another epoll event.

However, via a subtle chain of events, this can cause a bug for a
half-closed connection.  Suppose the connection is already half-closed in
the other direction - that is, we've already called shutdown(SHUT_WR) on
the socket for which we're getting the event.  In this event we're getting
the last batch of data in the other direction, and also a FIN.  This can
result in EPOLLIN, EPOLLRDHUP and EPOLLHUP events simultaneously.

We read the last data from the socket and successfully splice it to the
other side.  Since there is no data in the pipe, we exit the forwarding
loop.  However, because we did read data, we don't set the eof flag.

Because we don't set eof, we don't (yet) propagate the FIN to the other
side, or set FIN_SENT_(!fromsidei).  Therefore we don't (yet) recognize
this as a clean termination and set the CLOSING flag.  We would correct
this when we get our next event, however before we can do so we process
the EPOLLHUP event.  Because we haven't recognized this as a clean close
we assume it is an abrupt close and send an RST to the other side.

To avoid this, don't stop attempting to forward data on this path.
Continue for at least one more loop.  If we're at EOF, we'll recognize it
on the next splice(2).  If not it gives us an opportunity to forward more
data without returning to the mail epoll loop.

Link: https://bugs.passt.top/show_bug.cgi?id=202
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
---
 tcp_splice.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/tcp_splice.c b/tcp_splice.c
index 1359d6b8..34ffea73 100644
--- a/tcp_splice.c
+++ b/tcp_splice.c
@@ -605,7 +605,7 @@ retry:
 				}
 			}
 
-			break;
+			continue;
 		}
 
 		conn->read[fromsidei]    += readlen > 0 ? readlen : 0;
-- 
2.54.0


  parent reply	other threads:[~2026-05-20 13:08 UTC|newest]

Thread overview: 8+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-05-20 13:08 [PATCH 0/6] Fix race condition while closing spliced connections David Gibson
2026-05-20 13:08 ` [PATCH 1/6] tcp_splice: Improve error reporting David Gibson
2026-05-20 14:31   ` Stefano Brivio
2026-05-20 13:08 ` David Gibson [this message]
2026-05-20 13:08 ` [PATCH 3/6] tcp_splice: Clean up flow control path for splice forwarding David Gibson
2026-05-20 13:08 ` [PATCH 4/6] tcp_splice: Simplify tracking of read/written bytes David Gibson
2026-05-20 13:08 ` [PATCH 5/6] tcp_splice: Simplify EPOLLRDHUP / eof / FIN handling David Gibson
2026-05-20 13:08 ` [PATCH 6/6] tcp_splice: Simplify shutdown(2) handling David Gibson

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20260520130851.436931-3-david@gibson.dropbear.id.au \
    --to=david@gibson.dropbear.id.au \
    --cc=passt-dev@passt.top \
    --cc=pholzing@redhat.com \
    --cc=sbrivio@redhat.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
Code repositories for project(s) associated with this public inbox

	https://passt.top/passt

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for IMAP folder(s).