Description
We randomly get the following unobserved task exception in our logs:
Unobserved Task Exception: System.AggregateException: A Task's exception(s) were not observed either by Waiting on the Task or accessing its Exception property. As a result, the unobserved exception was rethrown by the finalizer thread. (Unable to read data from the transport connection: Der E/A-Vorgang wurde wegen eines Threadendes oder einer Anwendungsanforderung abgebrochen..)
---> System.IO.IOException: Unable to read data from the transport connection: Der E/A-Vorgang wurde wegen eines Threadendes oder einer Anwendungsanforderung abgebrochen..
---> System.Net.Sockets.SocketException (995): Der E/A-Vorgang wurde wegen eines Threadendes oder einer Anwendungsanforderung abgebrochen.
--- 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<System.Int32>.GetResult(Int16 token)
at System.Net.Security.SslStream.EnsureFullTlsFrameAsync[TIOAdapter](TIOAdapter adapter)
at System.Net.Security.SslStream.ReadAsyncInternal[TIOAdapter](TIOAdapter adapter, Memory`1 buffer)
at System.Net.Http.HttpConnection.ReadBufferedAsyncCore(Memory`1 destination)
at System.Net.Http.HttpConnection.RawConnectionStream.ReadAsync(Memory`1 buffer, CancellationToken cancellationToken)
--- End of inner exception stack trace ---
I managed to narrow this down to the ClientWebSocket close handshake and can reproduce this (see Reproduction Steps below). It happens when the closing of the connection takes too long after the close handshake finished. I think the issue is here:
|
await finalReadTask.AsTask().WaitAsync(TimeSpan.FromMilliseconds(WaitForCloseTimeoutMs)).ConfigureAwait(false); |
When WaitAsync() throws a TimeoutException, it gets ignored, but the exception from the original finalReadTask (which may happen later) is never observed in this case.
Reproduction Steps
using System.Net.WebSockets;
namespace WebApplication2
{
public class Program
{
public static async Task Main(string[] args)
{
TaskScheduler.UnobservedTaskException += (obj, args) =>
{
Console.Error.WriteLine("Unhandled exception: " + args.Exception);
};
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
app.UseWebSockets();
app.Use(async (HttpContext context, RequestDelegate next) =>
{
WebSocket webSocket = await context.WebSockets.AcceptWebSocketAsync();
await webSocket.ReceiveAsync(new ArraySegment<byte>(new byte[4096]), CancellationToken.None);
await webSocket.CloseOutputAsync(WebSocketCloseStatus.NormalClosure, "normal", CancellationToken.None);
await Task.Delay(10_000);
});
await app.StartAsync();
ClientWebSocket clientWebSocket = new ClientWebSocket();
await clientWebSocket.ConnectAsync(new Uri("ws://localhost:5065"), CancellationToken.None);
await clientWebSocket.CloseOutputAsync(WebSocketCloseStatus.NormalClosure, "normal", CancellationToken.None);
await clientWebSocket.ReceiveAsync(new ArraySegment<byte>(new byte[4096]), CancellationToken.None);
clientWebSocket.Dispose();
await Task.Delay(5_000);
GC.Collect(2);
GC.WaitForPendingFinalizers();
await Task.Delay(100_000);
}
}
}
Expected behavior
No unobserved task exception.
Actual behavior
Unobserved task exception:
Unobserved Task Exception: System.AggregateException: A Task's exception(s) were not observed either by Waiting on the Task or accessing its Exception property. As a result, the unobserved exception was rethrown by the finalizer thread. (Unable to read data from the transport connection: Der E/A-Vorgang wurde wegen eines Threadendes oder einer Anwendungsanforderung abgebrochen..)
---> System.IO.IOException: Unable to read data from the transport connection: Der E/A-Vorgang wurde wegen eines Threadendes oder einer Anwendungsanforderung abgebrochen..
---> System.Net.Sockets.SocketException (995): Der E/A-Vorgang wurde wegen eines Threadendes oder einer Anwendungsanforderung abgebrochen.
--- 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<System.Int32>.GetResult(Int16 token)
at System.Net.Security.SslStream.EnsureFullTlsFrameAsync[TIOAdapter](TIOAdapter adapter)
at System.Net.Security.SslStream.ReadAsyncInternal[TIOAdapter](TIOAdapter adapter, Memory`1 buffer)
at System.Net.Http.HttpConnection.ReadBufferedAsyncCore(Memory`1 destination)
at System.Net.Http.HttpConnection.RawConnectionStream.ReadAsync(Memory`1 buffer, CancellationToken cancellationToken)
--- End of inner exception stack trace ---
Regression?
No response
Known Workarounds
No response
Configuration
.NET 6.0.11 on Windows 11 x64.
Other information
No response
Description
We randomly get the following unobserved task exception in our logs:
I managed to narrow this down to the ClientWebSocket close handshake and can reproduce this (see Reproduction Steps below). It happens when the closing of the connection takes too long after the close handshake finished. I think the issue is here:
runtime/src/libraries/System.Net.WebSockets/src/System/Net/WebSockets/ManagedWebSocket.cs
Line 985 in ac2ffdf
When
WaitAsync()throws aTimeoutException, it gets ignored, but the exception from the originalfinalReadTask(which may happen later) is never observed in this case.Reproduction Steps
Expected behavior
No unobserved task exception.
Actual behavior
Unobserved task exception:
Regression?
No response
Known Workarounds
No response
Configuration
.NET 6.0.11 on Windows 11 x64.
Other information
No response