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
- Unloading the
AppDomainviaAppDomain.Unload(appdomain)disconnects and cleans up theAppDomaininstance, but theServerIdentityobjects remain and accumulate. - 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

ServerIdentity instance key retention paths

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?