I have a multi-threaded C++Builder GUI app, which communicates with a third-party app via COM.
I need to call methods of the COM object from several threads, and I'm protecting access with a mutex. Apparently, the main GUI thread must use STA model, but my worker threads need to use MTA. The COM object is constructed in an MTA thread.
Everything works fine except access to the COM object from the GUI thread, due to the MTA/STA mismatch.
I've read a bit about marshalling, but haven't tried to implement it, because the examples I've seen seem to require different access semantics depending the the current apartment model, and I really would like to have code that (from a programmer's POV) doesn't care about the current apartment model.
So, is there an idiomatic way to write COM code that operates on the 'same' object, but can be called from both STA and MTA threads?
Put the COM object interface into the Global Interface Table and let the GIT handle the marshalling for you. When any thread requests the COM interface, the GIT checks the calling apartment and will provide a direct pointer or a suitable proxy accordingly. Your code won't know the difference (or care), just use the returned interface normally as needed.
This is documented on MSDN:
Accessing Interfaces Across Apartments
Related
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.
I have read a LOT of material about Windows Form projects not supporting MTA. I get it. However, I also have read about Background worker, async/await and BeginInvoke use with such solutions. This and this are just a couple of examples. Here's one that even uses MSMQ. Some of the examples I have reviewed go way back to VB6 days.
I need to augment a Windows Form project with code to interact with a vendor service via API calls that could benefit from async capability. This being 2014, what is the best way to approach this? I use VB NET and have VS 2010 for my development.
Ideally, I would like to create a class library with the logic to interact with the vendor and just return the results to my Windows Form project. Can that be done?
The fact that MTA is not supported doesn't mean that you can't use multiple threads. The MTA model is just one way to use multiple threads, but because it's difficult to implement objects for that model, Windows Form uses the STA model instead.
The important effect of this is just that it means that the main thread in the application takes care of everything that has to do with the user interface. You can start as many threads as you like/need, but whenever anything from those threads needs to be displayed in the user interface, they have to use the Invoke method to let that update be done in the main thread.
There are already asynchronous method in the framework, for example the BeginRead and BeginWrite methods in the System.IO.FileStream class. You can have a look at those for some hints on how asynchronous methods are used in the framework.
If the API is synchronous, you would make asynchronous methods by simply starting a new thread that does the API call and then executes a callback method when it is done. As it's that thread that is waiting for the response, the call doesn't occupy the main thread.
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.
As the question states, can a shared method of an object be multithreaded? I don't quite having threading down in my skillset, otherwise I would test myself. On the other hand, I am involved in designing class that could be part of a multithreaded application in VB.Net.
If you mean "is it safe for a shared method to be called from multiple threads at once" - the answer is "it depends". A method itself isn't multi-threaded or single-threaded; threads and methods are very separate things.
If your shared method is called from multiple threads, then unless there's any synchronization to say otherwise, it will be executed concurrently on those threads. That can definitely cause a problem if your method uses shared state without appropriate safeguards. However, if the method either takes care when accessing shared resources (e.g. using locks) or it doesn't access any state which is shared between threads, that's fine.
Yes, it can. Any method can become a thread.
Yes, shared methods can be executed simultaneously by multiple threads. In fact, they often are. You do not have as much control over which threads are executing shared methods as compared to instance methods. Consider an ASP.NET application for example. Different page requests may come in on different threads. If you call a shared method in your web application then there is a high probability that it is getting executed by multiple threads.
This is an incredibly important point when designing an API. All self respecting API authors go to extremes to make sure all shared/static methods are thread-safe. Afterall, it would be ridiculously onerous to make a caller of your API synchronize access to every single shared/static method you provide. Take a look at the documentation Microsoft provides for almost all classes in the BCL.
Any public static (Shared in Visual Basic) members of this type are
thread safe. Any instance members are not guaranteed to be thread
safe.
I have yet to run across a static method provided by Microsoft that was not thread-safe.1 And that is good because it makes life easier for you and I.
1If you know of one let me know.
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.