-
-
Notifications
You must be signed in to change notification settings - Fork 2.5k
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
starving timeout with async_io
on closed connections
#6971
Comments
Please share the actual code you are using. Your example |
the original code in the async_io callback is this: let mut buf = [0; HANDSHAKE_BYTES_LEN];
let raw_fd = incoming_stream.as_raw_fd();
let std_stream =
unsafe { ManuallyDrop::new(std::net::TcpStream::from_raw_fd(raw_fd)) };
let peek_res = std_stream.peek(&mut buf);
match peek_res {
Ok(peek_len) if peek_len < HANDSHAKE_BYTES_LEN => {
Err(io::ErrorKind::WouldBlock.into())
}
res => res.map(|_| contains_tls_handshake_fragment(&buf)),
} (see the original code: https://git.proxmox.com/?p=proxmox.git;a=blob;f=proxmox-rest-server/src/connection.rs;h=3815a8f40c082410c8e0091f4a57541f616003d2;hb=refs/heads/master#l473 ) the reason we do this is because we want to look at the data sent from the client and decide if it's a tls handshake, so we either continue with an encrypted connection or handle an unencrypted HTTP request while i understand that this violates the contract of
) |
Yeah, that definitely violates the API contract. Unfortunately the OS provides no way to do what you want, so you're out of luck. It's not a Tokio limitation. As for the issue itself, I guess the request is to fail more gracefully when the API contract is violated? |
One question is why the timeout future is not being scheduled anymore when running into this. I get that we're holding this wrong and FWIW, we have a stop-gap for this specific case where we check if the But that we have to do that to avoid spinning completely is not what is unexpected to me, rather, for the current code I'd have expected that if the client disconnects the tokio timeout will still get hit after 10s, leading "only" to at max 10s of a spinning thread, i.e. due to us holding it wrong. |
The problem is that |
ok while i get that, two things are still surprising here:
the questions are: should async_io "yield" (or the rust equivalent) between async_io callback calls ? |
The timeout future can't be scheduled for execution because it's already busy running. It's stuck inside this call to It is reasonable to make |
Version
tokio v1.41.1
tokio-macros v2.4.0
Platform
Linux hostname 6.11.0-1-pve #1 SMP PREEMPT_DYNAMIC PMX 6.11.0-1 (2024-10-23T15:32Z) x86_64 GNU/Linux
Description
Is it expected behaviour that i can easily prevent a timeout from happening with
async_io
on closed connections?I tried this code:
(In our real code we call peek on the underlying socket to check if there is enough data available, and if not, we return WouldBlock)
After that, i connect to the server with
nc localhost 65000
If i cancel the nc connection (with CTRL+C) before the 5 seconds, the timeout is never reached and it loops forever in the async_io callback
If i don't close the connection (regardless if i send data or not), the timeout is reached normally.
I would have expected the timeout to trigger in both cases, but it does not.
The text was updated successfully, but these errors were encountered: