开发者

Check COM Interface still alive?

In COM how does one verify that a pointer to a COM object still has a valid object on the other end?

I have an issue where this following bit of code attempts to check if the m_pServer pointer is still alive, however when that application exposing that interface is killed this bit of code crashes the application. Can anybody advice on how to check the pointer before using it?

if (FAILED(m_pServer->StillAlive())) { // do something }

This code fails if m_pServer is no longer in memory.

EDIT:

EXCEPTION: First-chance exception at 0x7728fbae (kernel32.dll) in Client40.exe: 0x800706BA: The RPC server is unavailable.

CALL STACK:

    kernel32.dll!RaiseException()  + 0x58   
    rpcrt4.dll!RpcRaiseException()  + 0x3e  
    rpcrt4.dll!NdrProxyErrorHandler()  + 0x28   
    rpcrt4.dll!NdrProxySendReceive()  + 0xa4    
    rpcrt4.dll!NdrProxySendReceive()  + 0x119   
    rpcrt4.dll!NdrComplexArrayMarshall()  + 0x26d   
--> Client40.exe!SlaveDriver::run()  Line 97 + 0x14 C++  //Runs while loop, to handle requests
    Client40.exe!DThread::tfunc(void * thisptr=0x0047e694)  Line 56 + 0xd   C++
    Client40.exe!_threadstartex(void * p开发者_JAVA百科td=0x01b20e00)  Line 241 + 0xd  C
    kernel32.dll!BaseThreadInitThunk()  + 0x12  
    ntdll.dll!RtlInitializeExceptionChain()  + 0x63 
    ntdll.dll!RtlInitializeExceptionChain()  + 0x36 


What you're trying to do here is simply not possible. Because m_pServer lives in another process you're really asking the following question

Is Process XXX still running?

This is simply not an answerable question in the world of windows (or linux / unix). You can never reliably answer the question because the moment the question is answered it's result can be invalidated. Process's can terminate at any point in time including between your check and the access of the COM object.

However a slightly different version of this question is answerable

Was Process XXX still running?

The only way to approach a problem like this is to perform the operation in question and simply expect it to fail. If it succeeds then great you've answered the modified version of the question. If it fails then you need to interpret the failure to determine if the operation failed or the process is gone.

This is the only way to properly handle this situation.


It is up to you to manage the lifetime of the COM object. As long as you have a live pointer to the interface, you have to have at least one AddRef() call on the interface. The final Release() call will delete the object and the pointer goes stale. Using it afterwards will crash your program randomly, usually with an AV. There is no way to detect if it is stale.

You could set m_pServer to NULL when you make your final Release() call.


First-chance exceptions from COM are caught by the proxy and reported as error codes. If you continue past the first-chance exception, you should see the proxy return RPC_SERVER_UNAVAILABLE, which you should handle as appropriate.


Fundamentally, you never check this. It's can only give a useless answer. Consider the following hypothethical example:

if (CoCheckAlive(ptr)) {
  ptr->Foo();
}

Even if CoCheckAlive returned true, that result would not guarantee that the remote server would stay alive long enough to make the next call. That's why you just make the call, and handle failure cases (including RPC_E_SERVERDIED) afterwards.


Since it is a Exception couldn't you just __try it? You could set up an Exception filter to just catch the RPC-Server not available Exception. See http://msdn.microsoft.com/en-us/library/s58ftw19%28VS.80%29.aspx for further explanation on how to do this.


Just write a wrapper method that checks for failed and catches the exception and report it as a failure.


1 - Check the HRESULT inside your code - not just general FAILED - that will give you the place from which you can report more to user and or start alternative action (like close the app gracefully). Actual HRESULT may or may not be exactly RPC_SERVER_UNAVAILABLE - so firt assign it ti a var so that you can see it in debugger (and don't go jumping at first chance exceptions - they are for debbuging lower layers of code).

2 - If you actually get exception thrown in your C++ code then first place a general catch around it and then look at it in debugger. This case would probably come from come kind of smart pointer trying to be too smart :-)

In any case, leave your code a flag to know what happened and close COM references gracefully - just because the server died doesn't mean that you have to leak :-)

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜