Runtime: ObjectDisposedException / SocketsHttpHandler in .NET 2.1

Created on 11 Oct 2018  路  9Comments  路  Source: dotnet/runtime

Hello,

While upgrading our Web application from .NET Core 2.0.9 to 2.1.4, we started to see some ObjectDisposedException popping up (roughly 30 mins after application start), stating that SocketsHttpHandler could no longer be used.

Googling a bit led us to dotnet/runtime#27327. As this was supposed to fixed in 2.1.5, we decided to wait for it to be released.

Now, running on 2.1.5 we're still experiencing them.

I've trimmed down the project as much as I could into the simplest possible repro case I could come up with.

Steps:

  • Run the app (which should display some proxied json payload)
  • Refresh it regularly
  • Around 25~30mins the following exception happens
System.ObjectDisposedException

System.ObjectDisposedException: Cannot access a disposed object.
Object name: 'SocketsHttpHandler'.
   at System.Net.Http.SocketsHttpHandler.CheckDisposed()
   at System.Net.Http.SocketsHttpHandler.SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
   at System.Net.Http.DelegatingHandler.SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
   at System.Net.Http.DiagnosticsHandler.SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
   at Microsoft.Extensions.Http.Logging.LoggingHttpMessageHandler.SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
   at Microsoft.Extensions.Http.Logging.LoggingScopeHttpMessageHandler.SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
   at System.Net.Http.HttpClient.FinishSendAsyncBuffered(Task`1 sendTask, HttpRequestMessage request, CancellationTokenSource cts, Boolean disposeCts)
   at Web.Controllers.HomeController.InvokeSearch() in C:\REDACTED\src\Backend\Controllers\HomeController.cs:line 46
   at Web.Controllers.HomeController.SearchAsync() in C:\REDACTED\src\Backend\Controllers\HomeController.cs:line 23
   at Microsoft.AspNetCore.Mvc.Internal.ActionMethodExecutor.TaskOfIActionResultExecutor.Execute(IActionResultTypeMapper mapper, ObjectMethodExecutor executor, Object controller, Object[] arguments)
   at System.Threading.Tasks.ValueTask`1.get_Result()
   at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.InvokeActionMethodAsync()
   at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.InvokeNextActionFilterAsync()
   at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.Rethrow(ActionExecutedContext context)
   at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.Next(State& next, Scope& scope, Object& state, Boolean& isCompleted)
   at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.InvokeInnerFilterAsync()
   at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.InvokeFilterPipelineAsync()
   at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.InvokeAsync()
   at Microsoft.AspNetCore.Builder.RouterMiddleware.Invoke(HttpContext httpContext)
   at Microsoft.AspNetCore.Diagnostics.ExceptionHandlerMiddleware.Invoke(HttpContext context)
bug tenet-compatibility

Most helpful comment

I did a check...the issue is on you Startup setup. You do this
```c#
ProxyAwareHttpClientHandler handler = new ProxyAwareHttpClientHandler(proxy);
services
.AddHttpClient(Options.DefaultName)
.ConfigurePrimaryHttpMessageHandler(() =>
{
return handler;
});


But [guide says](https://docs.microsoft.com/en-us/dotnet/api/microsoft.extensions.dependencyinjection.httpclientbuilderextensions.configureprimaryhttpmessagehandler?f1url=https%3A%2F%2Fmsdn.microsoft.com%2Fquery%2Fdev15.query%3FappId%3DDev15IDEF1%26l%3DEN-US%26k%3Dk(Microsoft.Extensions.DependencyInjection.HttpClientBuilderExtensions.ConfigurePrimaryHttpMessageHandler);k(SolutionItemsProject);k(DevLang-csharp)%26rd%3Dtrue&view=aspnetcore-2.1) `The delegate should return a new instance of the message handler each time it is invoked.`
`ProxyAwareHttpClientHandler` is disposed after some time but you return "same" disposed instance...I think you need to do something like
```c#     
Uri proxy = Configuration.GetValue<Uri>("http_proxy");
services
.AddHttpClient(Options.DefaultName)
.ConfigurePrimaryHttpMessageHandler(() =>
{
     return new ProxyAwareHttpClientHandler(proxy);
});

With this fix it works on your repro.

All 9 comments

Repro project: Repro.zip

@geoffkizer

@karelz @davidsh @geoffkizer Is there anything I could do on my side to help move this issue forward?

We rollbacked on top of 2.0.x and running against a no longer supported version makes us... well... uncomfortable :wink:

@nulltoken we didn't get to it yet, sorry (a bit busy with other investigations for last few weeks :().
I hope we will have time to take a look next week.

Which OS does it happen on? Windows or Linux?
I assume you tried to repro it outside of ASP.NET, but failed, right?

I did a check...the issue is on you Startup setup. You do this
```c#
ProxyAwareHttpClientHandler handler = new ProxyAwareHttpClientHandler(proxy);
services
.AddHttpClient(Options.DefaultName)
.ConfigurePrimaryHttpMessageHandler(() =>
{
return handler;
});


But [guide says](https://docs.microsoft.com/en-us/dotnet/api/microsoft.extensions.dependencyinjection.httpclientbuilderextensions.configureprimaryhttpmessagehandler?f1url=https%3A%2F%2Fmsdn.microsoft.com%2Fquery%2Fdev15.query%3FappId%3DDev15IDEF1%26l%3DEN-US%26k%3Dk(Microsoft.Extensions.DependencyInjection.HttpClientBuilderExtensions.ConfigurePrimaryHttpMessageHandler);k(SolutionItemsProject);k(DevLang-csharp)%26rd%3Dtrue&view=aspnetcore-2.1) `The delegate should return a new instance of the message handler each time it is invoked.`
`ProxyAwareHttpClientHandler` is disposed after some time but you return "same" disposed instance...I think you need to do something like
```c#     
Uri proxy = Configuration.GetValue<Uri>("http_proxy");
services
.AddHttpClient(Options.DefaultName)
.ConfigurePrimaryHttpMessageHandler(() =>
{
     return new ProxyAwareHttpClientHandler(proxy);
});

With this fix it works on your repro.

@MarcoRossignoli HUGE thanks for helping us here with the investigation! Really appreciate it!
Seems to be answered, so closing. If there is reason to reopen, just let us know. Thanks!

@MarcoRossignoli Thanks for the help and the pointer to the documentation.

I'm going to test that and report here the outcome.

@MarcoRossignoli The outcome is .... wonderful. Thanks a lot! :heart:

image

Thank's for clear and complete repro...essential

Was this page helpful?
0 / 5 - 0 ratings