From ae3297f25d4bc26e000990cc1dfd16505ae9998a Mon Sep 17 00:00:00 2001 From: edef Date: Sat, 18 Nov 2023 22:56:02 +0000 Subject: [PATCH] FillBuf: don't poll a second time on EOF There is no hard guarantee that polling a second time will return Poll::Ready, and this is particularly likely to break in the EOF case, which is precisely where we don't need to do so at all. Both tokio::io::BufReader and futures::io::BufReader always attempt to read from the underlying reader when the buffer is empty, rather than fusing EOF. --- futures-util/src/io/fill_buf.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/futures-util/src/io/fill_buf.rs b/futures-util/src/io/fill_buf.rs index a1484c0322..6c14f71cd7 100644 --- a/futures-util/src/io/fill_buf.rs +++ b/futures-util/src/io/fill_buf.rs @@ -30,6 +30,8 @@ where let reader = this.reader.take().expect("Polled FillBuf after completion"); match Pin::new(&mut *reader).poll_fill_buf(cx) { + // We don't need to poll a second time for EOF, and doing so is likely to return Poll::Pending + Poll::Ready(Ok(&[])) => Poll::Ready(Ok(&[])), // With polonius it is possible to remove this inner match and just have the correct // lifetime of the reference inferred based on which branch is taken Poll::Ready(Ok(_)) => match Pin::new(reader).poll_fill_buf(cx) {