From 5c12e17ed4cb7fc4423f446e4ce0b6ca3b3a304e Mon Sep 17 00:00:00 2001 From: Josh Guilfoyle Date: Tue, 18 Jul 2023 14:24:56 -0700 Subject: [PATCH 1/2] poll: Do not clear readiness on short read/writes. The new mio_unsupported_force_poll_poll behaviour works the same as Windows (using level-triggered APIs to mimic edge-triggered ones) and it depends on intercepting an EAGAIN result to start polling the fd again. --- tokio/src/io/poll_evented.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tokio/src/io/poll_evented.rs b/tokio/src/io/poll_evented.rs index 875ad7e0d0a..9021888d349 100644 --- a/tokio/src/io/poll_evented.rs +++ b/tokio/src/io/poll_evented.rs @@ -166,7 +166,7 @@ feature! { Ok(n) => { // if we read a partially full buffer, this is sufficient on unix to show // that the socket buffer has been drained - if n > 0 && (!cfg!(windows) && n < len) { + if n > 0 && (!cfg!(windows) && !cfg!(mio_unsupported_force_poll_poll) && n < len) { self.registration.clear_readiness(evt); } @@ -197,7 +197,7 @@ feature! { Ok(n) => { // if we write only part of our buffer, this is sufficient on unix to show // that the socket buffer is full - if n > 0 && (!cfg!(windows) && n < buf.len()) { + if n > 0 && (!cfg!(windows) && !cfg!(mio_unsupported_force_poll_poll) && n < buf.len()) { self.registration.clear_readiness(evt); } From b50ef0e0cb91c80a0e6627e9c69ee55cfa8aacef Mon Sep 17 00:00:00 2001 From: Josh Guilfoyle Date: Tue, 18 Jul 2023 15:45:10 -0700 Subject: [PATCH 2/2] Leave a note about the mio_unsupported_force_poll_poll gotchas for even UNIX systems --- tokio/src/io/poll_evented.rs | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/tokio/src/io/poll_evented.rs b/tokio/src/io/poll_evented.rs index 9021888d349..f5e8cffb8f3 100644 --- a/tokio/src/io/poll_evented.rs +++ b/tokio/src/io/poll_evented.rs @@ -165,7 +165,9 @@ feature! { match self.io.as_ref().unwrap().read(b) { Ok(n) => { // if we read a partially full buffer, this is sufficient on unix to show - // that the socket buffer has been drained + // that the socket buffer has been drained. Unfortunately this assumption + // fails for level-triggered selectors (like on Windows or poll even for + // UNIX): https://github.com/tokio-rs/tokio/issues/5866 if n > 0 && (!cfg!(windows) && !cfg!(mio_unsupported_force_poll_poll) && n < len) { self.registration.clear_readiness(evt); } @@ -196,7 +198,9 @@ feature! { match self.io.as_ref().unwrap().write(buf) { Ok(n) => { // if we write only part of our buffer, this is sufficient on unix to show - // that the socket buffer is full + // that the socket buffer is full. Unfortunately this assumption + // fails for level-triggered selectors (like on Windows or poll even for + // UNIX): https://github.com/tokio-rs/tokio/issues/5866 if n > 0 && (!cfg!(windows) && !cfg!(mio_unsupported_force_poll_poll) && n < buf.len()) { self.registration.clear_readiness(evt); }