Open
Description
The following program hangs indefinitely when using the poll
-based Selector
:
#[tokio::main(flavor = "current_thread")]
async fn main() {
let response = reqwest::get("http://www.google.com").await.unwrap().text().await.unwrap();
println!("{}", response.len());
}
I am primarily targeting QNX Neutrino but experience the same behaviour on Linux with the mio_unsupported_force_poll_poll
flag (with or without the mio_unsupported_force_waker_pipe
flag).
After some investigations it seems that the problem is happening because the deregistration of the file descriptor associated with the TCP stream erases the still unhandled notification to wake the blocked-on future after the complete HTTP response has been received.
I pinpointed the issue to the modify_fds
method in src/sys/unix/selector/poll.rs
:
fn modify_fds<T>(&self, f: impl FnOnce(&mut Fds) -> T) -> T {
self.waiting_operations.fetch_add(1, Ordering::SeqCst);
// Wake up the current caller of `wait` if there is one.
let sent_notification = self.notify_waker.wake().is_ok();
let mut fds = self.fds.lock().unwrap();
// If there was no caller of `wait` our notification was not removed from the pipe.
if sent_notification {
self.notify_waker.ack_and_reset(); // ERASES PENDING NOTIFICATIONS
}
let res = f(&mut *fds);
if self.waiting_operations.fetch_sub(1, Ordering::SeqCst) == 1 {
self.operations_complete.notify_one();
}
res
}
The implementation has evolved a bit in the original poll implementation and seems to handle this case correctly.
Metadata
Metadata
Assignees
Labels
No labels