InfluxDB.Net icon indicating copy to clipboard operation
InfluxDB.Net copied to clipboard

Found memory leak in InfluxDbClientBase

Open marcel-kok opened this issue 8 years ago • 1 comments

This change fixed it. (HttpClient was never disposed)

private async Task<InfluxDbApiResponse> RequestAsync( IEnumerable<ApiResponseErrorHandlingDelegate> errorHandlers, HttpMethod method, string path, HttpContent content = null, Dictionary<string, string> extraParams = null, bool includeAuthToQuery = true, bool headerIsBody = false, TimeSpan? requestTimeout = null) { using (HttpClient client = GetHttpClient()) { var response = await RequestInnerAsync(client, requestTimeout, HttpCompletionOption.ResponseHeadersRead, CancellationToken.None, method, path, content, extraParams, includeAuthToQuery);

            string responseContent = String.Empty;

            if (!headerIsBody)
            {
                responseContent = await response.Content.ReadAsStringAsync();
            }
            else
            {
                IEnumerable<string> values;

                if (response.Headers.TryGetValues("X-Influxdb-Version", out values))
                {
                    responseContent = values.First();
                }
            }

            HandleIfErrorResponse(response.StatusCode, responseContent, errorHandlers);

            Debug.WriteLine("[Response] {0}", response.ToJson());
            Debug.WriteLine("[ResponseData] {0}", responseContent);

            return new InfluxDbApiResponse(response.StatusCode, responseContent);
        }
    }

    private async Task<HttpResponseMessage> RequestInnerAsync(
        HttpClient client,
        TimeSpan? requestTimeout,
        HttpCompletionOption completionOption,
        CancellationToken cancellationToken,
        HttpMethod method,
        string path,
        HttpContent content = null,
        Dictionary<string, string> extraParams = null,
        bool includeAuthToQuery = true)
    {
        if (requestTimeout.HasValue)
        {
            client.Timeout = requestTimeout.Value;
        }

        StringBuilder uri = BuildUri(path, extraParams, includeAuthToQuery);
        HttpRequestMessage request = PrepareRequest(method, content, uri);

        Debug.WriteLine("[Request] {0}", request.ToJson());
        if (content != null)
        {
            Debug.WriteLine("[RequestData] {0}", content.ReadAsStringAsync().Result);
        }

        return await client.SendAsync(request, completionOption, cancellationToken);
    }

marcel-kok avatar Sep 01 '17 18:09 marcel-kok

The usage of HttpClient is not correct. A new instance is created every time, and that is not the intended usage of HttpClient. HttpClient should be initialized only one time. Ideally it is disposed at the end too. Creating multiple HttpClients causes the SSL handshake to occur for every request and will lead to port exhaustion with high throughput. I'll be submitting a PR soon.

aschaible avatar Mar 29 '18 12:03 aschaible