RunningObjectTable and weak registration - com

I am trying to achieve the following functionality and I feel like I am really close but not quite there yet. I am posting this question to see if anyone may have already done something similar of has some insights into how this can best be achieved.
In one application (call it the MainApp) I am creating COM objects that I need to get access to from another application (call it the Tool). To achieve that, I need to register the objects in the MainApp to a ROT. For reasons outside the scope of this question I am using a custom IRunningObjectTable implementation that runs as a service; also, the COM objects need to register themselves into the ROT upon creation and de-register themselves when they are no longer needed. This means that the ROT must only hold weak references to the COM objects and must not prolong their lifetime.
Also, the ROT may be shut down while the COM objects still live. This must not lead to leaks or crashes in the MainApp.
The Tool will interrogate the ROT and get interfaces to the registered objects. It will extract information from the objects and hold them alive while doing so, but release them as soon as it is done with them.
The main problems I am facing are related to implementing the weak table registration and having the COM objects register and revoke themselves as opposed to being registered or revoked by their creator.
Thanks for any tips.

Related

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
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.

How to create a test to ensure no retain-cycle?

In one of mine project I have a quite complex data model.
I need a way to ensure that no retain cycle are created by me or by others colleagues and i want to use an automated approach.
There is a way to ensure that all the "dealloc" method are called?
You can try Static Analyzer (from menu : Product - Analyze or shorcut Shift+CMD+B). Or you create Unit Tests https://developer.apple.com/library/ios/documentation/ToolsLanguages/Conceptual/Xcode_Overview/UnitTestYourApp/UnitTestYourApp.html and check objects retainCount.
Leak instrument may help too : http://www.raywenderlich.com/2696/instruments-tutorial-for-ios-how-to-debug-memory-leaks , https://developer.apple.com/library/mac/documentation/developertools/conceptual/instrumentsuserguide/MemoryManagementforYouriOSApp/MemoryManagementforYouriOSApp.html
There is no way you can test such things automatically. Things you can do:
Have good coding standards and program architecture
Good architecture will prevent many retain cycles.
Be careful when using self in blocks (know when to use __weak id self).
Run Instruments and inspect leaks while your application is running
If you wish to do this you need to design & program it yourself.
For example you could:
Define "connection" as a strong reference to an instance of a class in your data model.
Define a protocol which provides either a "connected to" count method and one to return a connection by index or provides a connections iterator.
Have each class in your data model implement this protocol.
Now given a reference to your data model these protocol methods provide you with the "graph" (the objects are the nodes, the connections the arcs). Implement a cycle checking algorithm.
Now run the test at appropriate places during development & testing to check for accidental introduction of cycles.
You may be able to implement this without a protocol by using the facilities of the runtime, you can certainly given an arbitrary instance discover its ivars and whether an ivar is an object reference. You might get stuck though determining whether the ivar is strong or weak. While much more general this may be harder to implement, but once done...
HTH

Avoid COM marshalling

I'm a little confused about com threading models.
I have an inproc server and I want to create an interface accesible from any thread regardless of the threading-model and/or flags used in CoInitializeEx.
When passing interfaces from one thread to another I use CoMarshalInterface/CoUnmarshalInterface without problems but I want to know if exists any way to avoid that and directly pass the interface pointer.
I tried making the interface use neutral apartment but still have to call CoMarshalInterface/CoUnmarshalInterface to avoid problems.
Regards,
Mauro.
COM objects reside in one apartment only. Accessing a COM object via an interface pointer across apartment boundaries is never a good idea unless you're applicable scenario can utilize a free threaded marshaling aggregate. A free-threaded marshaller, essentially says that all clients of this interface, regardless of apartment and thread, are in the same process and will rely on the object itself to maintain synchronization and thread safety. The object itself must aggregate the free-threaded marshaller interface, so hopefully you're the author of it as well as the client code.
More information on free-threaded marshaling can be found at msdn.com, but one of their articles covering the object I tend to reuse again and again is this one.
I hope it helps you out.

"Finding" an object instance of a known class?

My first post here (anywhere for that matter!), re. Cocoa/Obj-C (I'm NOT up to speed on either, please be patient!). I hope I haven't missed the answer already, I did try to find it.
I'm an old-school procedural dog (haven't done any programming since the mid 80's, so I probably just can't even learn new tricks), but OOP has my head spinning! My question is:
is there any means at all to
"discover/find/identify" an instance
of an object of a known class, given
that some OTHER unknown process
instantiated it?
eg. somthing that would accomplish this scenario:
(id) anObj = [someTarget getMostRecentInstanceOf:[aKnownClass class]];
for that matter, "getAnyInstance" or "getAllInstances" might do the trick too.
Background: I'm trying to write a plugin for a commercial application, so much of the heavy lifting is being done by the app, behind the scenes.
I have the SDK & header files, I know what class the object is, and what method I need to call (it has only instance methods), I just can't identify the object for targetting.
I've spent untold hours and days going over Apples documentation, tutorials and lots of example/sample code on the web (including here at Stack Overflow), and come up empty. Seems that everything requires a known target object to work, and I just don't have one.
Since I may not be expressing my problem as clearly as needed, I've put up a web page, with diagram & working sample pages to illustrate:
http://www.nulltime.com/svtest/index.html
Any help or guidance will be appreciated! Thanks.
I have the SDK & header files, I know what class the object is, and what method I need to call (it has only instance methods), I just can't identify the object for targetting.
If this is a publicly declared class with publicly declared instance methods (i.e., you have the header for the class and it has instance methods in it), there is probably a way in this application's API to get an instance of the class. Either you are meant to create one yourself, or the application has one (or more) and provides a way to get it (or them). Look at both the header for the class in question and the other headers.
I initially said “there must be a way…”, but I changed it, because there is an alternative reason why the header would have instance methods: The application developer does not intend those instance methods for plug-in use (and didn't mark them appropriately), or did not mean to include that header in the application/SDK (they included it by accident). You may want to ask the application developer for guidance.
If it is not a publicly declared class or its instance methods are not publicly declared, then the application does not support you working with instances of the class. Doing so is a breach of the API contract—not a legal contract, but the expectations that the application has of its plug-ins. If you breach the API contract, you will cause unexpected behavior, either now (not necessarily on your own machine/in your own tests) or in the future.
If the class's public declaration contains only class methods, then perhaps what you're after is not an instance at all—you're supposed to send those messages to the class itself.
This is not possible without having you register each instance in a dictionary as it is created. I.e., override some common factory method at a higher level which does this bookkeeping work. This will fall down when you use delegates that you may not control though, keep that in mind.
I do question the need to even do this at all, but I don't know your problem as well as I perhaps would need to, to recommend a different, more apt way of accomplishing the actual task at hand.
Just as a corollary to the above; I did look at the runtime to see if there was anything that I actually forgot about, but there is not. So my above statement with regards to you requiring to do that bookkeeping yourself, still holds I'm afraid.
Edit:
Based on your diagram (my apologies, just noticed the link after I posted this answer); I would suggest that if you control the classes that are being returned to you, just add a property to them. I.e., add a "name" property that you can set and keep unique. Then just pass the message to each instance, checking whether or not that object is the one you want. It's not particularly clever or anything like that, but it should work for your purposes.

How can I stop someone from calling my COM interfaces APIs?

I have a COM inproc DLL that we are using in our product.
Now if someone finds out which interface and APIs we have exposed from the DLL then those APIs can be called easily.
Is there a way to stop unknown applications from calling my APIs?
Can we add some signature in COM?
The formal way of controlling use of your object is by implementing IClassFactory2 on the class factory that creates your COM objects.
Here's a link at MSDN explaining the interface.
IClassFactory2 at MSDN
The benefit of creating an implementation is that nobody can fetch an instance without clearing the hurdles of registration through IClassFactory2.
The downside is that you'll have to inspect all the locations where you are creating an object, to make sure that they haven't broken. Creating instances becomes more burdensome, although some languages already have facilities to make the process less painful (ex. VB6).
If you are trying to protect an object that has a lot of instantiation activity, you might want to go with Mastermind's method of adding a key parameter, or add an unlock method of some sort to your interfaces that must be called correctly before the component behind it can be used.
You could make your interfaces inheriting directly from IUnknown (without IDispatch) and not include the type library into the DLL. This way only those who have access to the type library will be able to find what interfaces are supported and the only other way to discover the interfaces will be to just guess. If you go this way you might also wish to minimize the number of classes exposed to registry (those that can be created with CoCreateInstance()) and use a set of factory methods of some dedicated registry-exposed class instead.
This implies that only vtable early-binding will work with your component. You will also be unable to use default call marshaling with this component (since no type library is included). And this is not real protection, just a way to hide things.
Nothing prevents you from adding a "key" parameter to the methods which will just return if the key is wrong.
Very simple but will do for starters.
Other than some sort of 'key' param, you can't prevent the curious from discovering your function and then calling it. All it takes is a debugger and some patience. To be totally secure you'd have to require some sort of certificate that authorized code could obtain but all others couldn't but that would mean you're code would have to be able to verify the certificate.