dotnet / dotnet/systemweb-adapters
SystemWeb.Adapters deadlocks after requesting a blazor page using InteractiveServer
- Dominant language
- C#
- Stars
- 384
- Forks
- 76
- Avg merge
- 2h 24m
- Merged PRs (30d)
- 1
Description
### Describe the bug
SessionLoadMiddleware is deadlocking on Blazor's InteractveServer request. When a page is requested using InteractiveServer the following 3 requests come through the middelware
1. GET: /counter
2. POST: /_blazor/negotiate
3. CONNECT: /_blazor
Since the CONNECT request stays open, the session is not properly committed and will stay in the heartbeat loop on the framework side.
Eventually, we will hit the HttpClient timeout on future requests.
### To Reproduce
Using the WebFormsToBlazor sample, replace the following in Program.cs
```
app.UseWhen(
(context) => HttpMethods.IsConnect(context.Request.Method) == false,
appBuilder => appBuilder.UseSystemWebAdapters());
```
with
```
app.UseSystemWebAdapters();
```
1. Navigate to the counter page
2. Navigate to any other page
Nothing will happen until the 100 second HttpClient timeout is hit
### Exceptions (if any)
HttpClient timeout
```
Microsoft.AspNetCore.SystemWebAdapters.SessionState.RemoteSession.RemoteAppSessionStateManager: Error: Unable to load remote session state for session
System.Threading.Tasks.TaskCanceledException: The request was canceled due to the configured HttpClient.Timeout of 100 seconds elapsing.
---> System.TimeoutException: The operation was canceled.
---> System.Threading.Tasks.TaskCanceledException: The operation was canceled.
---> System.IO.IOException: Unable to read data from the transport connection: The I/O operation has been aborted because of either a thread exit or an application request..
---> System.Net.Sockets.SocketException (995): The I/O operation has been aborted because of either a thread exit or an application request.
--- End of inner exception stack trace ---
at System.Net.Sockets.Socket.AwaitableSocketAsyncEventArgs.ThrowException(SocketError error, CancellationToken cancellationToken)
at System.Net.Sockets.Socket.AwaitableSocketAsyncEventArgs.System.Threading.Tasks.Sources.IValueTaskSource.GetResult(Int16 token)
at System.Net.Security.SslStream.EnsureFullTlsFrameAsync[TIOAdapter](CancellationToken cancellationToken, Int32 estimatedSize)
at System.Runtime.CompilerServices.PoolingAsyncValueTaskMethodBuilder`1.StateMachineBox`1.System.Threading.Tasks.Sources.IValueTaskSource.GetResult(Int16 token)
at System.Net.Security.SslStream.ReadAsyncInternal[TIOAdapter](Memory`1 buffer, CancellationToken cancellationToken)
at System.Runtime.CompilerServices.PoolingAsyncValueTaskMethodBuilder`1.StateMachineBox`1.System.Threading.Tasks.Sources.IValueTaskSource.GetResult(Int16 token)
at System.Net.Http.HttpConnection.SendAsync(HttpRequestMessage request, Boolean async, CancellationToken cancellationToken)
--- End of inner exception stack trace ---
at System.Net.Http.HttpConnection.SendAsync(HttpRequestMessage request, Boolean async, CancellationToken cancellationToken)
at System.Net.Http.HttpConnectionPool.SendWithVersionDetectionAndRetryAsync(HttpRequestMessage request, Boolean async, Boolean doRequestAuth, CancellationToken cancellationToken)
at System.Net.Http.DiagnosticsHandler.SendAsyncCore(HttpRequestMessage request, Boolean async, CancellationToken cancellationToken)
at System.Net.Http.HttpClient.g__Core|83_0(HttpRequestMessage request, HttpCompletionOption completionOption, CancellationTokenSource cts, Boolean disposeCts, CancellationTokenSource pendingRequestsCts, CancellationToken originalCancellationToken)
--- End of inner exception stack trace ---
--- End of inner exception stack trace ---
at System.Net.Http.HttpClient.HandleFailure(Exception e, Boolean telemetryStarted, HttpResponseMessage response, CancellationTokenSource cts, CancellationToken cancellationToken, CancellationTokenSource pendingRequestsCts)
at System.Net.Http.HttpClient.g__Core|83_0(HttpRequestMessage request, HttpCompletionOption completionOption, CancellationTokenSource cts, Boolean disposeCts, CancellationTokenSource pendingRequestsCts, CancellationToken originalCancellationToken)
at Microsoft.AspNetCore.SystemWebAdapters.SessionState.RemoteSession.RemoteAppSessionStateManager.GetSessionDataAsync(String sessionId, Boolean readOnly, HttpContext callingContext, CancellationToken token)
at Microsoft.AspNetCore.SystemWebAdapters.SessionState.RemoteSession.RemoteAppSessionStateManager.CreateAsync(HttpContext context, SessionAttribute metadata)
```
Contributor guide
Assessment
This issue has not been assessed yet.