WaitForSingleObject с дескриптором потока застревает при запуске regsvr32.exe - PullRequest
4 голосов
/ 24 июля 2011

У меня есть поток A, который создает другой поток B, чем поток A ожидает, используя WaitForSingleObject, чтобы дождаться смерти потока B.

Проблема в том, что даже если поток B возвращается из потока "thread_func", поток A не получает сигнал! .

Я знаю, что поскольку я добавил трассировки (OutputDebugString) в конец thread_func (основная функция потока B), и я вижу, что поток B завершает свое выполнение, но поток A никогда не выходит из WaitForSingleObject.

Теперь я должен также добавить, что этот код находится в COM-объекте, и описанный выше сценарий происходит, когда я вызываю regsvr32.exe (он застрял!), Поэтому я считаю, что поток A исходит из DllMain.

Любые идеи, почему поток A не получает сигнал?!?!

Ответы [ 2 ]

14 голосов
/ 24 июля 2011

Возможно, вы столкнулись с проблемой блокировки загрузчика.Windows имеет внутреннюю критическую секцию, которая блокируется при загрузке / выгрузке DLL или при запуске / остановке потока (DllMain всегда вызывается внутри этой блокировки).Если ваш ожидающий поток A заблокировал эту критическую секцию (т. Е. Вы ожидаете где-то от DllMain), а другой поток B пытается завершить работу и попытаться получить эту критическую секцию загрузчика, у вас есть тупик.возникает тупик, просто запустите ваше приложение из отладчика VS IDE и после того, как оно застрянет, прервите выполнение.Затем посмотрите на все запущенные потоки и запишите стек каждого из них.Вы должны иметь возможность следить за каждым стеком и видеть, что ожидает каждый поток.

4 голосов
/ 24 июля 2011

Я думаю, что @DXM прав.Документация о том, что именно вы можете или не можете делать внутри DllMain, очень скудна, и ее трудно найти, но суть в том, что вы, как правило, должны держать это как минимум - инициализировать внутренние переменные и тому подобное, но это примерноэто.

Еще одно замечание, которое я хотел бы сделать, это то, что * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 1005загружает DLL в свое адресное пространство с помощью LoadLibrary, вызывает GetProcAddress, чтобы получить адрес функции с именем DllRegisterServer, а затем вызывает эту функцию.Гораздо чище (и, в конечном счете, легче) выполнять работу самостоятельно, что-то вроде этого:

HMODULE mod = LoadLibrary(your_COM_file); 
register_DLL = GetProcAddress(mod, "DllRegisterServer"); 
if ( register_DLL == NULL) { 
        // must not really be a COM object... 
} 

if ( S_OK != register_DLL()) { 
        // registration failed. 
} 
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...