Проблема возникла. Имеем стандартный Singleton, сгенерированный визардом ATL.
Имеем метод
LONG CExeModule::Unlock()
{
LONG l = CComModule::Unlock();
if (l == 0)
{
bActivity = true;
BOOL b = SetEvent(hEventShutdown); // tell monitor that we transitioned to zero
}
return l;
}
Проблема в том, что данный метод вызывается два раза со значение (l == 0) и происходит падение (только на WINDOWS Server 2003) при втором вызове так как hEventShutdown уже закрыт.
Т.е. я в отдельном процессе пишу следующий код:
IUnknown* ptr2;
HRESULT hRes = ::CoCreateInstance(CLSID_STObj, NULL, CLSCTX_LOCAL_SERVER, IID_IUnknown, (void**)&ptr2); ptr2->Release();
После вызова ptr2->Release() в Singleton вызывается Unlock(), счетчик блокировок становится равным 0, посылаетсыя эвент монитору. Казалось бы все нормально завершается, но в _tWinMain() после цикла обработки событий стоит _Module.RevokeClassObjects() при вызове этого метода в итоге приходим к вызову CComClassFactorySingleton::FinalRelease(), в котором вызывается CoDisconnectObject(m_Obj.GetUnknown(), 0);
Так вот эта GetUnknown() вызывает последовательно CComObjectGlobal::AddRef() и Release(), которые в свою очередь вызывают _Module.Lock() и Unlock().
Но счетчик блокировок модуля уже был равен нулю! Как такое может быть?!