Assume that I have two processes, A and B. Process A instantiates an IDispatch object in process B (Process A loads the proxy stub, marshalling is done through it). During this, process B crashes and the IDispatch object goes down with it. Process A still has a pointer to something, but when it tries to call a function on that IDispatch object, the marshaller returns an error code. What is that error code? E_POINTER? E_FAIL?
You'll normally get RPC_E_SERVERFAULT. This is unpleasant behavior, the server is usually toast after this. A fix is available in Vista and up with IGlobalOptions. Check this blog post for details.
Related
When dealing with interprocess COM objects, is it safe to cast a IDispatch* into an IUnknown*, without using QueryInterface ?
Here our IDispatch object comes from an other process OtherProcess.exe.
And a colleague of mine says that I should call QueryInterface on the IDispatch so as to get an IUnknown.
Currently I'm doing:
void CComThrowDispatch::CheckCOMAvailabilty() const
{
IUnknown * pIUnknown = m_spDispatchDriver.p;
// is this line above a problem ?
// m_spDispatchDriver is an ATL CComDispatchDriver
// it handles an object instanciated in another process.
// m_spDispatchDriver.p is of type IDispatch*
if (pIUnknown == nullptr) return;
bool bComObjectReachable = ::CoIsHandlerConnected(pIUnknown) == TRUE;
if (bComObjectReachable == false)
{
throw MyException;
}
}
My problem with his suggestion: I am dealing with cases (access violations) when the OtherProcess.exe has crashed or has been killed. It seems calling any functions like Invoke on the IDispatch that encapsulates any objects from this no longer exisiting OtherProcess.exe provokes these access violations (EDIT: comments and answers reveals that this latest assumption was completely false!).
That's why I'm trying to protect the application testing ::CoIsHandlerConnected(pIUnknown); which takes an IUnknown as parameter.
But by calling QueryInterface on the IDispatch, like my colleague advises me to do, I am afraid to fall back in the same problem I am trying to solve: This IDispatch handles an object that no longer exists, and QueryInterface to an IUnknown would just be Undefined Behaviour all the same (EDIT again, this assumption is also false).
Am I really wrong when I just do the cast ?
What is the common way to deal with dead interprocess COM objects ?
This is the begining of the definition of IDispatch in OAIdl.h, which is declared as deriving from IUnknown.
MIDL_INTERFACE("00020400-0000-0000-C000-000000000046")
IDispatch : public IUnknown
{
public:
virtual HRESULT STDMETHODCALLTYPE GetTypeInfoCount(
/* [out] */ __RPC__out UINT *pctinfo) = 0;
Casting IDispatch to IUnknown in C++ (like static_cast<IUnknown*>(pDispatch)) yields exactly the same pointer value, because IDispatch derives from IUnknown. OTOH, doing QueryInterface for IID_IUnknown on pDispatch may return a different pointer, but it's still a legit operation. In fact, this is how to get the identity of a COM object, say, to check if two interfaces are implemented by the same COM object (a hard COM rule which always work inside the same COM apartment).
That said, the proxy COM object implemented by the COM marshaller may be caching interfaces, so the call to IDispatch::QueryInterface may return S_OK and a valid IUnknown identity of the proxy, despite the remote server already went down. That is, such operation might not be causing an instant IPC call.
In your case, to test if the COM server is still alive and well, I'd simply call IDispatch::GetTypeInfoCount on the proxy object you already have. That would actually cause an IPC call (or a round-trip over the wire, if the server runs on a different host).
In case the remote server has crashed or is unavailable, you'd likely receive a CO_E_OBJNOTCONNECTED error (could perhaps be a different error code, but certainly not S_OK).
Note though, doing an extra IPC call just to check if the server is available might be a costly operation, depending on your scenario.
In order to detect whether the object is remote CoIsHandlerConnected would QueryInterface the argument anyway (for IProxyManager etc), so it does not matter whether you provide the pointer you already have, or you additionally query for IUnknown. Your QueryInterface call has not effect on the status of the remote object: whether the object is remote or not, whether remote object is dead or not - CoIsHandlerConnected has the same result for you regardless of your additional QueryInterface. Hence, there is no need to do it.
Then another note is that it is still safe to call IDispatch::Invoke if remote object is dead (out-of-process server crashed etc). The proxy simply returns error code without undefined behavior. That is, it looks like you don't need CoIsHandlerConnected at all, and if you experience access violations in context of client process, then you probably have other issues to resolve first.
No, you should always you QueryInterface.
Just because you've com an IUnknown interface it doesn't mean you can directly cast it to IDispatch. COM may have given you a proxy to the underlying object, which means that the pointer has nothing to do with IDispatch.
Likewise, an implementation may wrap an object that implements IDispatch and when you call QueryInterface it delegates to this object. Or you may have a pointer to a COM objects that delegates to an outer IUnknown.
So, basically, never directly cast, even if you think it'll work, because things may change over time. Calling QueryInterface is rarely a performance bottleneck and therefore not worth avoiding.
Hallo,
I have a quite strange problem in one of my C++ projects:
I wrote a C++ Socket wrapper, that tries to connect to a given host and port (via IPv4/TCP) and throws a SocketException (derived from std::runtime_error), if an error occurs (e.g. 'Connection refused'). The exception is caught properly and an error message is written to console as expected, but apparently the destructor of my Socket class is not called (it should output a message to std::cerr, too, but the message only appears if connection works and Socket is destroyed later on if it goes out of stack, e.g. on end of the function that tries to utilize the socket). The destructor should close the encapsulated socket, but on exception thrown the socket remains open (you can see it with lsof as socket of unknown type), so no code in the destructor seems to be executed at all).
As I couldn't reproduce this problem with a simple testcase, my guess is that it somehow has to do with the quite complex structure of my project: I have a core application containing the code for the Socket class and providing a Singleton class which offers methods that implement the protocol used for communication and return the results of a request, each call to one of these methods generates its own instance of a Socket and provides it with the necessary information about host and port to use. To simplify socket generation and managment, a std::auto_ptr is used, which should delete the Socket if method has finished and stack is cleaned up, which works properly according to console output, but it should work the same way on an exception thrown, at least that is what was my opinion until now.
The core is able to load plugins in shared object format by dlopen and gets a pointer to the plugin's class instance via an extern C declared function in the shared object.
This instance now uses the Singleton provided by the core to communicate with the server and show retrieved data.
My question is: are there limitations to stack unwinding when using shared objects, or where should I look for the thing I missed out to make this work properly?
If your exception is thrown from the constructor, the destructor will not be called.
Ok, forget that one. Another look in the code showed that there was the possibility that an exception could have been thrown already in constructor so that the destructor would not have been called, as it's described in C++ standard. Not throwing in the constructor solved the problem. That's what programming in Java is doing to your C++ skills ^^
Excuse the noise, please.
If you are programming on linux, you might be triggering a problem where the exception thrown from a shared library is not caught properly (problem with exception type determining). This problem is explained here and here, and I am sure you could google up more pages explaining the same problem.
If that is a problem, I am still looking for a solution :(
What's the cheapest way for a JavaScript like setTimeout-function in C++?
I would need this:
5000 miliseconds from now, start function xy (no parameters, no return value).
The reason for this is I need to initialize COM for text to speech, but when I do it on dll attach, it crashes.
It works fine however if I do not call CoInitialize from dllmain.
I just need to call CoInitialize and CoCreateInstance, and then use the instance in other functions. I can catch the uninitialized instance by checking for NULL, but I need to initialize COM - without crashing.
Calling CoInitialize() from DllMain() is a bad thing to do; there are LOTS of restrictions on what you can do from DllMain(); see here: http://blogs.msdn.com/larryosterman/archive/2004/04/23/118979.aspx
Even if it DID work reliably then initialising COM from within DllMain() isn't an especially nice thing to do as COM is initialised per thread and you don't know what the application itself wants to do with regards to COM apartments for the thread that you want to initialise COM for... This means that you might initialise COM in one way and then the application might need to initialise it in another way and might fail because of what your DLL had done...
You COULD spin up a thread in DllMain() as long as you are careful (see here http://blogs.msdn.com/oldnewthing/archive/2007/09/04/4731478.aspx) and then initialise COM on that thread and do all your COM related work on that thread. You would need to marshal whatever data you need to use COM with from whatever thread you're called on to your own COM thread and make the COM call from there...
And then there's the question of whether the instance of the COM object that you create (could you reliably do what you want to do) would be usable from the thread that was calling into your DLL to make the call... You do understand how you'd have to marshal the interface pointer if required, etc?
Alternatively you should expose YOUR functionality via COM and then have the application load your DLL as a COM DLL and everything will work just fine. You can specify the apartment type that you need and the app is responsible for setting things up for you correctly.
So, in summary, you don't need the answer to your question.
When it is OK to stop the execution for 5 seconds entirely, you can use the Winapi Sleep function. Beware that the documentation of Sleep minds some possible problems with CoInitialize and Messages.
I have a COM class CMyCOMServer implementing IMyInterface in one application, both with correct GUIDs. CMyCOMServer::QueryInterface will return S_OK (and cast itself to the right type) if IUnknown or IMyInterface is requested, otherwise it returns E_NOINTERFACE.
In another app on the same PC, I call:
HRESULT hr = ::CoCreateInstance(__uuidof(CMyCOMServer), 0, CLSCTX_SERVER,
__uuidof(IMyInterface ),(void **)&pInterface);
It returns E_NOINTERFACE. So I assumed I was doing something wrong and added a breakpoint on CMyCOMServer::QueryInterface. I found that when CoCreateInstance is called, QueryInterface is triggered several times for different interfaces:
First, IUnknown is requested - no problem
Then, several interfaces like IMarshall etc are requested... these are not supported so E_NOINTERFACE is returned
Finally, IMyInterface is requested. I verify QueryInterface returns S_OK and sets (IMyInterface *)this as the interface pointer, as expected
So my confusion is why the calling CoCreateInstance is leaving me a NULL pointer and return code of E_NOINTERFACE, when the COM server app is clearly returning the interface I ask for?
EDIT: my client app calls CoInitialize(NULL) at startup, this makes no difference.
If your COM server is running in a different process, or a different apartment in the same process, COM needs to know how to package and transmit parameters when you make calls to your interface. This process is called "marshaling".
If you define a custom interface, you need to implement marshaling for it using one of the following approaches.
Standard marshaling: have the MIDL compiler to generate a proxy
and stub which you must register on the system. This is probably the best option since you have already defined your interface.
OLE Automation marshaling: you define an automation compatible
custom interface and use the
marshaller which is already part of
the COM framework
Custom marshaling: you implement the methods of IMarshal
When you are debugging your COM server, although you see that you are returning your custom interface in the call to QueryInterface, it does not make it across the process boundary because COM cannot figure out how to marshal that interface, hence the client sees E_NOINTERFACE.
UPDATE (based on your comment)
If this is an existing COM server app then you probably already have a proxy/stub. You need to register this on both the client and server. Could it be that you were testing this on a new machine(s) and you simply forgot to register this? To register you simply do regsvr32 on the proxy/stub dll.
This happens because COM subsystem tries to marshal your custom interface (IMyInterface) and simply has no idea how to do that. That happens either because the server is out-proc or because the server is in-proc and the thread of the consumer application that calls CoCreateInstance() has called CoInitialize()/ CoInitializeEx() incorrectly so that "multithreaded apartment" is requested as mentioned in the article user Thomas refers to in the other answer.
If you only need an in-proc server you could suppress marshalling by ensuring that the thread calling CoCreateInstance() either calls CoInitialize() or CoInitializeEx() with COINIT_APARTMENTTHREADED to enforce "single-threaded apartment".
If you need an out-proc server you can't get around marshalling. In the latter case you could do one of the following:
implement IMarshal - least preferable
add proxy/stubs and register them for your custom interface
(not sure if it will work for out-proc, but it's the simplest) if your interface can be marshalled with automation marshaller simply include a typlib into the resources of your COM server and register that typelib in the registry.
Could this be the threading model problem that Raymond Chen wrote about?
Edit in reply to the comment:
If your threading model is incompatible with the threading model of the object you're creating, then COM marshalling kicks in. And if the marshalling stuff isn't there, the error that comes out is E_NOINTERFACE, because the marshalling interface is missing.
It's more about threading models than about marshalling, really.
The previous comments about E_NOINTERFACE returned because marshalling interface is missing was very helpful,
however,
for us the answer/fix was to force the main application (the one calling CoCreateInstance) to be STA (single threaded apartment), and this was done by setting an advanced linker option, i.e.:
"CLR Thread Attribute" is set to "STA threading attribute"
or on the link command line you do:
"/CLRTHREADATTRIBUTE:STA"
This prevents a mix of MTA and STA, which causes a call across threads.
Hope someone else finds this helpful.
currently I'm struggling trying to use a COM dll on a simple system that I've made. Everything compiles successfully, but in runtime the CoCreateInstace is returning S_OK, but somehow my object pointer is returning NULL.
This interface pointer is created on my class header. The weirdest thing is that instantiating this same pointer type on the method stack results in a correct object, but subsequent calls to __hook turn on an access violation when trying to create a BASE com class.
Some other aspects that might be useful:
Tried to run the program with CoInitalizeEx started as COINIT_MULTITHREADED and COINIT_APARTMENTTHREADED
The project is a dll which uses the COM dll in it
I've tried the same method without starting a new thread and the error persists
I've made a test program ( no threads, executable ) and the object is created normally, and hooked correctly. So my guess it is something related to it being a DLL itself or threaded related.
PS: As bonus question, why google doesn't return anything favorable related to COM? :)
It sounds like a bug in the COM object's implementation of IUnknown::QueryInterface - not setting the output pointer but returning S_OK.
CoCreateInstance for an in-proc server is basically:
Load the DLL into memory
Call DllGetClassObject to get the class factory
Call IClassFactory::CreateInstance from the class factory which allocates a new object
Call IUnknown::QueryInterface on the new object to get the desired interface.
Returning NULL but S_OK at any step should result in a crash, except for the QI call at the end.
Found the problem: The module attribute was defined on a static library, and that made the COM object go crazy; Moving it to the DLL source resolved the problem.