-
Notifications
You must be signed in to change notification settings - Fork 4.7k
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
[QUIC] handle concurrent stream reads and concurrent stream writes #52627
Comments
Tagging subscribers to this area: @dotnet/ncl Issue DetailsWhile we do support concurrent read and write, concurrent reads (e.g. multiple read operations pending) and concurrent writes (multiple writers) are problematic. There is note in the code but there is no logic to prevent this and it will certainly not work correctly at the moment. (and tests) We should add logic to trace pending IO and most likely block the concurrency like SslStream does.
|
We don't generally enforce this across all Streams (e.g. HTTP request/response streams). Generally speaking, it's up to the user to ensure they don't use the Stream concurrently. That said, I don't have a strong opinion here. Maybe @stephentoub does. |
SslStream throws PNSP while other stream types may not. I would think that we either block it or or we make sure it works properly. I think if we want to support it, we should add tests and fix the state handling. I'm not sure if that would be ever beneficial to HttpClient or Kestrel. Since QUIC will not be public API in 6.0 we may focus on the simple cases and decide later. |
I don't think we should ever make it work properly, it's not worth the effort/overhead. I do think we should have a consistent philosophy here and apply it across all our various Streams. |
+1 I'd be fine if we want to detect / fail for it as SslStream does, especially if doing so helps to simplify something else (e.g. because of the enforcement we don't need to worry about unsafe code doing something problematic due to concurrent access, or we can better use a cache without additional synchronization, or some such thing). But I also think it's ok to say that at most one read and at most one write operation at a time is supported, and attempting more than that is a violation of the contract. We generally don't make any guarantees about multithreaded use of non-thread-safe types, and this is an extension of that. |
Let's say in a multiplayer game, there are players A, B and C, each with a single QUIC stream connected to the server. Every write is a small buffer containing a complete message that could otherwise be handled lock-free and zero-copy. The message is small enough to be complete, yet messages can be out of order. It is not streaming huge data that should not be mixed up out of order. |
It'd be a good reference for other stream types to support concurrent IO. SignalR could benefit from it. |
For a scenario like that, just use a lock (or better, an async lock via SemaphoreSlim) to ensure mutual exclusion. You could even build it as a wrapping stream so it works with any arbitrary underlying Stream. |
Triage: We should be consistent with other APIs (like SslStream) and block mulit-Writes / multi-Reads proactively rather to make it work incorrectly. |
For my case, I'd wrap the QUIC stream as a tunnel for SignalR transport and then use Hub invocation instead of messing with the bytes myself. |
While we do support concurrent read and write, concurrent reads (e.g. multiple read operations pending) and concurrent writes (multiple writers) are problematic. There is note in the code but there is no logic to prevent this and it will certainly not work correctly at the moment. (and tests)
We should add logic to trace pending IO and most likely block the concurrency like SslStream does.
This will possibly also help with #32142
The text was updated successfully, but these errors were encountered: