-
Notifications
You must be signed in to change notification settings - Fork 744
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Inconsistent edge-triggered behavior between platforms #1612
Comments
On tokio, we have an optimization which is disabled on windows because of this behavior. |
This is actually not strictly inconsistent, it's a choice we made with the initial Windows (re)implementation. It's documented here: https://docs.rs/mio/latest/mio/struct.Poll.html#draining-readiness, that we only guarantee that we return events once Since then I've opened #1611 to reconsider this. I think that issue is about the same thing as this issue.
IIRC for epoll and kqeue you need to (e.g.) read all bytes in the buffer before you get another event. This happens when you call
Like I said this is something we decided on before for initial consistency, but it's something we can reconsider.
Is a small read here with a small buffer that is completely filled? Because that shouldn't retrigger (create another events), only with a big (enough) buffer not completely filling it.
Something we might be changing in #1611. |
By small read here I meant if I write 15 bytes to a buffer and then read 5, there are still 10 bytes left to be read. EDIT: this is quite confusing considering the usage of "short" read elsewhere (in your issue and the SO post I linked) means a read that doesn't fill the provided buffer
I was actually incorrect here, what I was really testing when I was playing around was i.e. The following reliably produces inconsistent behavior right now stream.write(b"Hello world!");
stream.flush();
expect_events(&mut poll, &mut events, |e| e.is_readable());
let mut buf = [0; 5];
stream.read(&mut buf);
stream.write(b"Hello world!");
stream.flush();
expect_events(&mut poll, &mut events, |e| e.is_readable()); because the second But I was wrong in saying that just a small read is inconsistent. i.e. stream.write(b"Hello world!");
stream.flush();
expect_events(&mut poll, &mut events, |e| e.is_readable());
let mut buf = [0; 5];
stream.read(&mut buf);
expect_events(&mut poll, &mut events, |e| e.is_readable()); will panic across all platforms, because (my notion of) a "small" read alone is not enough to reset the readable interest. |
Sorry I missed this entirely -- this seems to be a very similar issue so we can close this and move the discussion there if you'd like |
Yes let's move it to #1611. |
The current edge triggered behavior on Windows is not consistent with the behavior of
EPOLLET
inepoll
orEV_CLEAR
inkqueue
. This can be seen with the following minimal example: https://github.com/sullivan-sean/mio-edge-triggeredOn Windows, interests for a source are cleared on event receipt and reset on
WouldBlock
errors. If a source is polled until readable and then aread
call is made this does not reset the interests. Another call toread
after all data has been read (to throwWouldBlock
) is necessary to reset interests.Edge triggered behavior, as described in the epoll docs, "only delivers events when changes occur on the monitored file descriptor." There is a question of whether a partial read is actually considered a change on a file descriptor, i.e. is the Windows behavior still technically "edge-triggered" and in some ways more correct by waiting for
WouldBlock
to reset interests? In playing around with theepoll
andkqueue
behavior, it seems that even if only a small read is performed and there is still more data to be read, a subsequent poll will still emit a read-readiness event. This suggests that in practice short reads do reset "read-readiness" in edge-triggered mode.For consistency, then, sources on Windows would need to reset interests on successful I/O and not just
WouldBlock
errors.The text was updated successfully, but these errors were encountered: