Fix incoming connections during app shutdown causing delays #64099
+212
−17
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Fixes #58947
There is a race between when the
IHostApplicationLifetime.ApplicationStopping
token fires and when theIServer.StopAsync
(which unbinds connection listeners) runs (ref). SignalR was listening toApplicationStopping
and closing all currently active connections, however new incoming connections right afterApplicationStopping
fires are still accepted by theIServer
implementation and SignalR was processing them and letting them stay around until theIServer
implementation ungracefully closed them (30 second default).The first part of the fix was to add a lock around
CloseConnections
and then callCloseConnections
when creating a new connection if we know that the application is stopping.While testing to make sure this fix worked, I noticed that connections with stateful reconnect enabled weren't shutting down quickly, this was because when we first created the connection we immediately ran
CancelPreviousPoll
which would clear the cancellation token being used to stop the websocket read loop. The fix was to not runCancelPreviousPoll
for the first connection and move where theCancellationToken
is created to be after the previous connection is canceled.