-
Notifications
You must be signed in to change notification settings - Fork 5.2k
Fix data race on incoming MsQuicStream abort #69483
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
Conversation
|
Tagging subscribers to this area: @dotnet/ncl Issue DetailsThis PR fixes a data race which we occasionally hit when running Http.Funcional.Tests in a tight loop. The data race this PR fixes occurs like this:
|
|
To consider:
|
On x86/64, the memory model of the hardware is strong enough that no fences are emitted. The only impact is potentially prohibiting certain optimizations the JIT might otherwise do. Generally it's negligible. On ARM, the hardware has a weaker memory model and the JIT does need to emit a fence in most situations. |
| state.SendErrorCode = (long)streamEvent.PEER_RECEIVE_ABORTED.ErrorCode; | ||
| // make sure the SendErrorCode above is commited to memory before we assign the state. This | ||
| // ensures that the code is read correctly in SetupWriteStartState when checking without lock | ||
| Volatile.Write(ref Unsafe.As<SendState, int>(ref state.SendState), (int)SendState.Aborted); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think you need the Volatile.Write here since you're inside a lock. AFAIK that should emit memory barriers if necessary. @stephentoub please correct me if I'm wrong.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The comment suggests the concern is the reordering of the write to SendErrorCode and the write to SendState. The volatile is necessary to prevent that reordering. There is a fence as part of releasing the lock, but that only guarantees that neither write will move past the lock exit, not that they won't move past each other.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🤦 yep, I should have read that comment 🤣
src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/MsQuic/MsQuicStream.cs
Show resolved
Hide resolved
ManickaP
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks.
|
Test failure is #69387 |
This PR fixes a data race which we occasionally hit when running Http.Funcional.Tests in a tight loop.
The data race this PR fixes occurs like this:
HandleEventPeerRecvAborted). And sets_state.SendState = SendState.AbortedSetupWriteStartState, we check the_state.SendState == SendState.Aborted. This is done outside the lock to avoid locking when stream is in a terminal state._state.SendErrorCodewhich hasn't been set yet by the MsQuic thread -> we throwQuicOperationAbortedExceptioninstead ofQuicStreamAbortedExceptionwith appropriate error code.Example test failure due to the race