I am debugging a memory leak in an application. I have noticed a constant raise in instances of SocketAsyncEventArgs, AsyncContinuation, LogEventInfo, Layout, NetworkTarget delegates etc. All retained on the managed heap by references from System.Threading.OverlappedData instances.
The application uses a Chainsaw target for logging.
I've looked at the implementation of UdpNetworkSender and I think the leak originates from the Socket.SendToAsync callback:
private void SocketOperationCompleted(object sender, SocketAsyncEventArgs e)
{
AsyncContinuation userToken = e.UserToken as AsyncContinuation;
Exception exception = null;
if (e.SocketError != SocketError.Success)
{
exception = new IOException("Error: " + e.SocketError);
}
e.Dispose();
if (userToken != null)
{
userToken(exception);
}
}
The thread pool has a cache of IO Completion objects that eventually hold references to the SocketAsyncEventArgs.
Since the SocketAsyncEventArgs.UserToken is not set to null, the AsyncContinuation user token is not garbage collected. The AsyncContinuation in turn holds a ref to NLog LogEventInfo instance with the message string and layout.