Search code examples
httpclientcoveritymessage-handlers

Coverity - MessageHandler/HttpClient leak issue


Coverity sees in the following code that the messageHandler going out of scope, leaks the resource it refers to.

"System.Net.Http" Version="4.3.4" .net 6.0

Could you please suggest what I can do here?

1. "new System.Net.Http.HttpClientHandler(){UseCookies = false}" creates a new resource.
2. Assigning: "messageHandler" = resource returned from "new System.Net.Http.HttpClientHandler(){UseCookies = false}".
                    var messageHandler = config.MessageHandler ?? new HttpClientHandler() { UseCookies = false };
                    
3. Condition "config.UseOAuth", taking false branch.
                    if (config.UseOAuth)
                    {
…
4. Resource "messageHandler" is not closed or saved in "HttpClient".
                    var client = new HttpClient(messageHandler, messageHandler != config.MessageHandler) { BaseAddress = new Uri(config.Url) };
                   
5. Condition "!config.UseOAuth", taking true branch.
                    if (!config.UseOAuth)
                    {
                        //add request headers
                    }
6. Variable "messageHandler" going out of scope leaks the resource it refers to.
                    return RestService.For<AClass>(client, AClass.RefitSettings);
                });
        }

Thank you!


Solution

  • It looks like Coverity lack some information how HttpClient looks inside.
    It says: 4. Resource "messageHandler" is not closed or saved in "HttpClient".
    Internally HttpClient is forwarding your messageHandler to it's one base class called HttpMessageInvoker, then store it in variable _handler and there we can find Dispose method

            protected virtual void Dispose(bool disposing)
            {
                if (disposing && !_disposed)
                {
                    _disposed = true;
                    if (_disposeHandler)
                    {
                        _handler.Dispose();
                    }
                }
            }
    

    So messageHandler is saved inside HttpClient

    In .NET 6 you don't need to reference package System.Net.Http at all as it's available without anything with version 6.0.0

    Note: What I wrote here is based on version 6.0.0


    I see other issue, if this code is called multiple times and if HttpClient takes argument messageHandler from config.MessageHandler, then if one of those HttpClient get disposed other one will contained disposed object, so when you are creating HttpClient you have pass false as second argument if it's config.MessageHandler, or just use messageHandler != config.MessageHandler

    var client = new HttpClient(messageHandler, messageHandler != config.MessageHandler) { BaseAddress = new Uri(config.Url) };