Проверить работоспособность COM-интерфейса?

Как в COM проверить, что указатель на COM-объект все еще имеет действительный объект на другом конце?

У меня проблема, когда следующий фрагмент кода пытается проверить, жив ли указатель m_pServer , однако, когда приложение, открывающее этот интерфейс, убивается, этот фрагмент кода вызывает сбой приложения. Кто-нибудь может посоветовать, как проверить указатель перед его использованием?

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

Этот код не работает, если m_pServer больше не находится в памяти.

РЕДАКТИРОВАТЬ:

ИСКЛЮЧЕНИЕ: Первоочередное исключение по адресу 0x7728fbae (kernel32.dll) в Client40.exe: 0x800706BA: Сервер RPC недоступен.

СТЕКЛО ВЫЗОВОВ:

    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 * ptd=0x01b20e00)  Line 241 + 0xd  C
    kernel32.dll!BaseThreadInitThunk()  + 0x12  
    ntdll.dll!RtlInitializeExceptionChain()  + 0x63 
    ntdll.dll!RtlInitializeExceptionChain()  + 0x36 
10
задан Sam 21 November 2011 в 13:19
поделиться

7 ответов

То, что вы пытаетесь сделать здесь, просто невозможно. Поскольку m_pServer живет в другом процессе, вы на самом деле задаете следующий вопрос

Процесс XXX все еще запущен?

На этот вопрос просто невозможно ответить в мире windows (или linux / unix). Вы никогда не сможете достоверно ответить на этот вопрос, потому что в момент ответа на вопрос его результат может быть аннулирован. Процесс может завершиться в любой момент времени, в том числе между вашей проверкой и доступом к COM-объекту.

Однако можно ответить на несколько иную версию этого вопроса

Был ли процесс XXX все еще запущен?

Единственный способ решить подобную проблему - это выполнить рассматриваемую операцию и просто ожидать, что она завершится неудачей. Если она завершится успешно, то вы ответили на модифицированную версию вопроса. Если она не удалась, то вам нужно интерпретировать неудачу, чтобы определить, не удалась ли операция или процесс пошел.

Это единственный способ правильно справиться с этой ситуацией.

6
ответ дан 4 December 2019 в 02:24
поделиться

Вы сами определяете время жизни COM-объекта. Пока у вас есть активный указатель на интерфейс, у вас есть , чтобы иметь хотя бы один вызов AddRef () в интерфейсе. Последний вызов Release () удалит объект, и указатель станет устаревшим. Его последующее использование приведет к случайному сбою вашей программы, обычно с AV. Невозможно определить, устарел ли он.

Вы можете установить для m_pServer значение NULL при последнем вызове Release ().

1
ответ дан 4 December 2019 в 02:24
поделиться

По сути, вы никогда не проверяете это. Это может дать только бесполезный ответ. Рассмотрим следующий гипотетический пример:

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

Даже если CoCheckAlive вернет true , этот результат не будет гарантировать, что удаленный сервер останется активным достаточно долго, чтобы сделать следующий вызов. Вот почему вы просто звоните, а потом обрабатываете случаи сбоя (включая RPC_E_SERVERDIED).

0
ответ дан 4 December 2019 в 02:24
поделиться

Первоочередные исключения из COM перехватываются прокси-сервером и сообщаются как коды ошибок. Если вы продолжите после исключения первого шанса, вы должны увидеть, что прокси-сервер возвращает RPC_SERVER_UNAVAILABLE, который вы должны обработать соответствующим образом.

1
ответ дан 4 December 2019 в 02:24
поделиться

Просто напишите метод-оболочку, который проверяет сбой, перехватывает исключение и сообщает об этом как об ошибке.

0
ответ дан 4 December 2019 в 02:24
поделиться

Поскольку это исключение, не могли бы вы просто __попробовать? Вы можете настроить фильтр исключений, чтобы просто перехватить исключение RPC-Server not available. См. http://msdn.microsoft.com/en-us/library/s58ftw19%28VS.80%29.aspx для дальнейшего объяснения того, как это сделать.

0
ответ дан 4 December 2019 в 02:24
поделиться

1 - Проверьте HRESULT внутри вашего кода - а не только общий FAILED - это даст вам место, из которого вы можете сообщить больше пользователю и или начать альтернативное действие (например, изящно закрыть приложение) . Фактический HRESULT может быть или не быть точно RPC_SERVER_UNAVAILABLE - поэтому сначала назначьте его ti var, чтобы вы могли видеть его в отладчике (и не переходите на исключения при первом шансе - они предназначены для отладки нижних слоев кода).

2 - Если вы действительно получаете исключение в своем коде C++, сначала поместите вокруг него общий улов, а затем посмотрите на него в отладчике. Этот случай, вероятно, возник из-за того, что умный указатель пытается быть слишком умным :-)

В любом случае, оставьте свой код флагом, чтобы знать, что произошло, и изящно закройте ссылки COM - просто потому, что сервер умер, это не значит что надо слить :-)

0
ответ дан 4 December 2019 в 02:24
поделиться
Другие вопросы по тегам:

Похожие вопросы: