comdcom

How to leverage DCOM garbage collector with custom marshaling? (IMarshal)


I'm working on a multi-tenant COM server that exposes classes with different interfaces in a hierarchy. Some of the classes implement IMarshal for more efficient custom marshaling using shared-memory for zero-copy exchange of immutable data buffers (based on "Inside COM+: Base Services" book). This works nicely but comes at the downside of losing automatic stub cleanup by the DCOM garbage collector if the client crashes or leaks handles. I've grown quite found of using COMGLB_FAST_RUNDOWN for fast stub cleanup after client crashes, and would very much like automatic cleanup also for IMarshal classes if possible.

I've already tried implementing IExternalConnection to intercept reference release events from the client-side proxy. However, this interface does not seem to be called for classes that also implement IMarshal. IFastRundown is similarly also not called for classes implementing IMarshal.

I'm reluctant to implementing my own watchdog to detect & handle client process crashes, since that would require manual bookkeeping of references held by each client for each object instance that implements IMarshal. This sounds like a lot of bookkeeping to me. Detecting the client process PID is furthermore inconvenient, especially if it needs to be done separately for each object reference due to the multi-tenant architecture. Leveraging the DCOM garbage collector would make everything much easier.

Any suggestions for how to enable the DCOM garbage collector also for classes implementing IMarshal?

I guess what I'm hoping for is some form of per-object event mechanism for being notified when client references are released that also sends an event if the client crashes.

Small reproducer project: https://github.com/forderud/SharedMemMarshal


Solution

  • Answering myself since I just found a solution to this problem.

    It's possible to introduce an extra COM object for maintaining references from the client-side proxy back to the server.

    The https://github.com/forderud/SharedMemMarshal project have been updated to do just this through a tiny RefOwner class that is marshalled using CoMarshalInterface/CoUnmarshalInterface from the server to the proxy. This both simplifies the impl. as well as hardening it to better cope with reference leaks and client process crashes.