Memory leak of ServerIdentity objects generated by AppDomain proxies?

Viewed 494

Problem
TLDR; I am seeing a steady leak of ServerIdentity objects for each transparent proxy object I create.

I am generating AppDomains as a mechanism to sandbox some 3rd party code execution, and utilizing MarshalByRefObject and appDomain.CreateInstanceAndUnwrap() to generate a transparent proxy to execute my code. However each instance I marshal also creates a corresponding ServerIdentity that is apparently held onto by an internal static class.

What I've tried

  1. Unloading the AppDomain via AppDomain.Unload(appdomain) disconnects and cleans up the AppDomain instance, but the ServerIdentity objects remain and accumulate.
  2. Calling RemotingServies.Disconnect(marshalbyrefobject) throws an exception as it apparently isn't for handling transparent proxies since it throws this error: System.Runtime.Remoting.RemotingException: 'Cannot call disconnect on a proxy.'

The closest I've come to finding an answer to this was this blog post describing a very similar issue. However there must be additional context to their code that I am missing.

dotMemory Screenshots

Number of new objects increases with each request, does not get garbage collected enter image description here

ServerIdentity instance key retention paths enter image description here

Edit 1
So I discovered what was causing the exception mentioned in bullet point number 2. Basically you can't call RemotingServices.Disconnect(proxyInstance) from the main AppDomain. It has to be done on the real MarshalByRefObject instance object created in the secondary AppDomain. Basically I created my own abstract implementation of MarshalByRefObject like so. I verified that Disconnect() is being called for each marshaled instance.

public abstract class SandboxedInstance : MarshalByRefObject
{
    public sealed override object InitializeLifetimeService()
    {
        // This override implementation ensures the lifetime of this object until Dispose() is called.
        return null;
    }

    /// <summary>
    /// Method called internally when containing Sandbox is disposed, automatically disposing this object.
    /// </summary>
    internal void Disconnect()
    {
        RemotingServices.Disconnect(this);
    }
}

However, this has not solved my problem. The ServerIdentity objects still seem to be lingering around despite RemotingServies.Disconnect(marshalbyrefobject) successfully being called. Is there anybody who understands the guts of whats going on? I can find very little documentation on this.

Edit 2
Is there anybody who can confirm this theory? I've read mentions that some remoting objects live past the point of Disconnect() but are eventually cleaned up. Based on this theory I ran dotMemory and watched to see if ServerIdentity objects were cleaned up over time, especially ones retained via Lease. This actually seems to be the case. Can anyone with knowledge on this issue confirm this?

0 Answers
Related