When using the Google.Apis.Translate.v2 package and creating and disposing TranslateService instances we have noticed a leak of IPv4 connections.
Minimal reproduction:
using System;
using System.Linq;
using System.Net;
using System.Threading.Tasks;
using Google.Apis.Services;
using Google.Apis.Translate.v2;
namespace Churyumov
{
class Program
{
private static readonly NetworkCredential s_clientIdentity =
new NetworkCredential(
"<YOUR>",
"<CREDENTIALS>");
private static readonly string[] s_foreignText =
new[]
{
"The quick brown fox jumps over the lazy dog",
"Le renard brun rapide saute sur le chien paresseux",
"Der schnelle braune Fuchs springt 眉ber den faulen Hund"
};
static async Task Main(string[] args)
{
var initializer = new BaseClientService.Initializer
{
ApplicationName = s_clientIdentity.UserName,
ApiKey = s_clientIdentity.Password,
GZipEnabled = true // << changing this to `false` prevents the leak
};
using (var service = new TranslateService(initializer))
{
var request = service.Detections.List(s_foreignText);
var response = await request.ExecuteAsync(default);
foreach (var result in response.Detections)
{
Console.WriteLine(string.Join(", ", result.Select(r => r.Language)));
}
}
Console.WriteLine("Check open connections here!");
}
}
}
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp2.2</TargetFramework>
<RootNamespace>Churyumov</RootNamespace>
<LangVersion>Latest</LangVersion>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Google.Apis.Translate.v2" Version="1.40.0.875" />
</ItemGroup>
</Project>
When inspecting the application on the Check open connections here line with lsof you can see the connection to the Google translate service has not been disposed:
$ lsof -p `pgrep dotnet` | grep IPv
dotnet 57839 willspeak 52u IPv4 0xd178e425407bd7f9 0t0 TCP 10.11.1.61:50431->lhr48s08-in-f10.1e100.net:https (ESTABLISHED)
It looks like the TwoWayDelegatingHandler created when the GZipEnabled option is set to true doesn't properly dispose of an inner handler:

Thanks for reporting this.
It's meant to be disposed in TwoWayDelegatingHandler here: https://github.com/googleapis/google-api-dotnet-client/blob/6133df9980b6f65b456564a2488e538dc43a08ef/Src/Support/Google.Apis.Core/Http/TwoWayDelegatingHandler.cs#L55
I'll investigate further.
Yeah, I looked at the code in this repo and can't see why it _wouldn't_ be disposed. I don't think that Dispose(bool disposing) should be conditionally calling the base like it does: https://github.com/googleapis/google-api-dotnet-client/blob/6133df9980b6f65b456564a2488e538dc43a08ef/Src/Support/Google.Apis.Core/Http/TwoWayDelegatingHandler.cs#L51
And instead should just call base.Dispose(disposing) either before or after disposing of it's own resources. I can't see how that would stop this being disposed though as we're dealing with an explicit dispose call rather than a finalizer.
OK, the bug is here: https://github.com/googleapis/google-api-dotnet-client/blob/6133df9980b6f65b456564a2488e538dc43a08ef/Src/Support/Google.Apis.Core/Http/TwoWayDelegatingHandler.cs#L51
That call should be the base.Dispose(true), not base.Dispose().
I'll create a PR to fix it.
Ah, just seen that you'd noticed this before me :) Thanks.
This is a problem because it means the Dispose(bool) method in the base DelegatingHandler is never getting called; so the inner handler is never being disposed of.
Nice! Thanks for the quick responses. Longer term I understand we should be moving to Google.Cloud.Translation.V2 but support for this is much appreciated. Any ETA for a fixed build of this library?
The build+release process has started for v1.40.1 - it should be available on nuget.org within a couple of hours.