-
Notifications
You must be signed in to change notification settings - Fork 4.8k
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
avoid NRE in MsQuicConnection ConnectAsync #56283
Conversation
Tagging subscribers to this area: @dotnet/ncl Issue DetailsThis is recent regression caused by #55468. fixes #56263
|
src/libraries/System.Net.Quic/src/System/Net/Quic/Implementations/MsQuic/MsQuicConnection.cs
Outdated
Show resolved
Hide resolved
state.ConnectTcs.SetException(ex); | ||
state.ConnectTcs = null; | ||
// This is opportunistic if we get exception and have ability to propagate it to caller. | ||
state.ConnectTcs.TrySetException(ex); |
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.
This is the change I was hinting at when asking about the race condition.
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 think I can do better fix. Instead of checking state of the task I can simply store TaskCompletionSource in ConnectAsync to local variable and return that. There is really no reason to drag it past Connect event.
@@ -234,15 +234,14 @@ private static uint HandleEventConnected(State state, ref ConnectionEvent connec | |||
|
|||
private static uint HandleEventShutdownInitiatedByTransport(State state, ref ConnectionEvent connectionEvent) | |||
{ | |||
if (!state.Connected && state.ConnectTcs != null) | |||
if (!state.Connected && state.ConnectTcs != null && !state.ConnectTcs.Task.IsCompleted) | |||
{ | |||
Debug.Assert(state.Connection != null); | |||
state.Connection = null; | |||
|
|||
uint hresult = connectionEvent.Data.ShutdownInitiatedByTransport.Status; | |||
Exception ex = QuicExceptionHelpers.CreateExceptionForHResult(hresult, "Connection has been shutdown by transport."); | |||
state.ConnectTcs!.SetException(ExceptionDispatchInfo.SetCurrentStackTrace(ex)); |
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.
This doesn't need to be TrySetException as well?
I did different fix @stephentoub, can you please take another quic look. To avoid fighting over global state, I store the original tcs in local variable so it would never NRE. And then the |
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.
Small nit, otherwise LGTM
This is recent regression caused by #55468.
When we fail faster than we can return
ConnectTcs
inConnectAsync
, it may be null and the return would fail.So instead of setting it to null to prefer double cleanup I added
Task.IsCompleted
check.fixes #56263
fixes #56454