The SocketAwaitable
class seems to be leaking resources in #SNMP v 9.0.3.
I think it is probably caused by strong reference.
So I prepared details that seems to be memory leak. I ran it in the situation where the following timeout occurs:
- The SNMP agent exists on host B, but it is not running.
- Running my test code (Console App) on host A.
My test code snippet is below:
private static async Task TestMemory()
{
// Running this code on host A
// The Snmp Agent on host B, but an agent is not listening...
var message = new GetRequestMessage(0x4bed, VersionCode.V1, new OctetString("public"), new List<Variable> { new Variable(new ObjectIdentifier("1.3.6.1.2.1.1.1.0")) });
for (int i = 0; i < 100; i++)
{
using (var cts = new CancellationTokenSource(TimeSpan.FromSeconds(0.5))) // timeout 500 msec.
{
try
{
var response = await message.GetResponseAsync(new IPEndPoint(IPAddress.Parse("IP OF HOST B"), 161))
.WithCancellation(cts.Token)
.ConfigureAwait(false);
}
catch (Exception ex)
{
Console.WriteLine("{0}", ex.Message);
}
}
}
message = null;
GC.Collect();
GC.WaitForPendingFinalizers();
GC.Collect();
}
private static async Task<T> WithCancellation<T>(this Task<T> task, CancellationToken cancellationToken)
{
var tcs = new TaskCompletionSource<bool>();
using (cancellationToken.Register(state => ((TaskCompletionSource<bool>)state).TrySetResult(true), tcs))
{
var completedTask = await Task.WhenAny(task, tcs.Task).ConfigureAwait(false);
if (task != completedTask)
{
throw new OperationCanceledException(cancellationToken);
}
}
return await task.ConfigureAwait(false);
}
The snapshot with dotMemory is below:
I think it is leaking with SocketAwaitable
and SocketAsyncEventArgs
.
It seems to leak in the following cases:
- When the SNMP Agent on the remote host does not respond (e.g. snmpd.exe is not listening):
CancellationTokenSource
raised anOperationCanceledException
exception.- The socket in the
GetResponseAsync(this ISnmpMessage, IPEndPoint)
method is not disposed.
Perhaps it may be necessary to overload the GetResponseAsync
method to receive CancellationToken
.