Skip to content
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

HttpConnection leaks UnobservedTaskExceptions #61256

Closed
MihaZupan opened this issue Nov 5, 2021 · 5 comments · Fixed by #80214
Closed

HttpConnection leaks UnobservedTaskExceptions #61256

MihaZupan opened this issue Nov 5, 2021 · 5 comments · Fixed by #80214
Assignees
Milestone

Comments

@MihaZupan
Copy link
Member

MihaZupan commented Nov 5, 2021

If the SocketsHttpHandler is not disposed, HttpConnection.Dispose will not be called in time to observe the exception from the readAheadTask. The Dispose will run as part of the finalizer, but since the TaskExceptionHolder in _readAheadTask is also finalizable, it may be too late as the execution order of finalizers is not guaranteed.

Impact: Noise
The exceptions that leak to UnobservedTaskExceptions would be ignored anyway, so there is no adverse side effects aside from noise.

I am able to reproduce the same thing on 5.0 as well. The code is pretty much the same on 3.1, so I assume it would repro there as well (haven't tried since I am relying on the ConnectCallback).

Example stack trace:

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: An existing connection was forcibly closed by the remote host..)
 ---> System.IO.IOException: Unable to read data from the transport connection: An existing connection was forcibly closed by the remote host..
 ---> System.Net.Sockets.SocketException (10054): An existing connection was forcibly closed by the remote host.
   --- 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.ReadAsyncInternal[TIOAdapter](TIOAdapter adapter, Memory`1 buffer)
   at System.Net.Http.HttpConnection.<CheckUsabilityOnScavenge>g__ReadAheadWithZeroByteReadAsync|44_0()
   --- End of inner exception stack trace ---
@ghost
Copy link

ghost commented Nov 5, 2021

Tagging subscribers to this area: @dotnet/ncl
See info in area-owners.md if you want to be subscribed.

Issue Details

If the SocketsHttpHandler is not disposed, HttpConnection.Dispose will not be called in time to observe the exception from the readAheadTask. The Dispose will run as part of the finalizer, but since the ExceptionHolder in _readAheadTask is also finalizable, it may be too late as the execution order is not guaranteed.

Impact: Noise
The exceptions that leak to UnobservedTaskExceptions would be ignored anyway, so there is no adverse side effects aside from noise.

I am able to reproduce the same thing on 5.0 as well. The code is pretty much the same on 3.1, so I assume it would repro there as well (haven't tried since I am relying on the ConnectCallback).

Author: MihaZupan
Assignees: -
Labels:

area-System.Net.Http

Milestone: -

@dotnet-issue-labeler dotnet-issue-labeler bot added the untriaged New issue has not been triaged by the area owner label Nov 5, 2021
@MihaZupan MihaZupan added the bug label Nov 5, 2021
@ghost ghost added in-pr There is an active PR which will close this issue when it is merged and removed in-pr There is an active PR which will close this issue when it is merged labels Nov 5, 2021
@karelz karelz removed the untriaged New issue has not been triaged by the area owner label Nov 16, 2021
@karelz karelz added this to the Future milestone Nov 16, 2021
@karelz
Copy link
Member

karelz commented Nov 16, 2021

Triage: Might be fixed by #60729
No large impact, Future.

@davidfowl
Copy link
Member

davidfowl commented Nov 30, 2021

Why not backport this one? It'll end up in people's logs (they're logging unobserved tasks).

@MihaZupan
Copy link
Member Author

I think we should fix this in 8.0. Leaking internal exceptions like this is ugly.

@MihaZupan MihaZupan self-assigned this Jan 4, 2023
@ghost ghost added the in-pr There is an active PR which will close this issue when it is merged label Jan 5, 2023
@ramonsmits
Copy link

I observe a lot of these via FirstChanceException logging:

System.IO.IOException: Unable to read data from the transport connection: Operation canceled.
 ---> System.Net.Sockets.SocketException (125): Operation canceled
   --- 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.Http.HttpConnection.<CheckUsabilityOnScavenge>g__ReadAheadWithZeroByteReadAsync|44_0()

I discovered that these are related to pooling. I can significantly reduce these by setting the PooledConnection* properties:

var handler = new SocketsHttpHandler
{
    PooledConnectionIdleTimeout = TimeSpan.FromHours(1),
    PooledConnectionLifetime = TimeSpan.FromHours(1),
};

Issue is that I cannot control all created HttpClients.

@ghost ghost removed the in-pr There is an active PR which will close this issue when it is merged label Feb 1, 2023
@ghost ghost locked as resolved and limited conversation to collaborators Mar 3, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.