отладочное приложение зависало при создании потока с использованием beginthreadex

#c #windows #multithreading

#c #Windows #многопоточность

Вопрос:

Я сталкиваюсь со странной проблемой на сайте, из-за которой наше приложение зависает при запуске. Я получаю аварийный дамп, сгенерированный пользовательским интерфейсом на сайте, и это показывает, что основной поток был заблокирован API beginthreadex. Вот стек вызовов:

 0:006> kv
ChildEBP 
0161ebb8 ntdll!KiFastSystemCallRet (FPO: [0,0,0])
0161ebbc ntdll!ZwWaitForSingleObject 0xc (FPO: [3,0,0])
0161ebf8 ntdll!RtlpWaitOnCriticalSection 0x1a3 (FPO: [2,7,4])
0161ec18 ntdll!RtlEnterCriticalSection 0xa8 (FPO: [1,1,0])
0161ec4c ntdll!LdrLockLoaderLock 0x133 (FPO: [SEH])
0161ecc8 ntdll!LdrGetDllHandleEx 0x94 (FPO: [SEH])
0161ece4 ntdll!LdrGetDllHandle 0x18 (FPO: [4,0,0])
0161ed30 kernel32!GetModuleHandleForUnicodeString 0x20 (FPO: [SEH])
0161f1a8 kernel32!BasepGetModuleHandleExW 0x17f (FPO: [SEH])
0161f1c0 kernel32!GetModuleHandleW 0x29 (FPO: [1,0,0])
0161f1cc kernel32!GetModuleHandleA 0x2d (FPO: [1,0,0])
0161f204 msvcr80!initptd 0x17
0161f224 msvcr80!beginthreadex 0x56
0161f248 ZQCommonStlp!ZQ::common::NativeThread::NativeThread 0x59 (FPO: [Non-Fpo]) (CONV: thiscall) 
...
  

Я ничего не получаю от этого стека вызовов, но просто знаю, что основной поток застрял при создании нового потока.
Это системная проблема?

Ответ №1:

Вы запускаете этот поток в DllMain (или какой-либо инициализации DLL)? Похоже, что оно зашло в тупик из-за печальноизвестной блокировки загрузчика. Смотрите следующие документы для получения подробной информации о том, что разрешено (очень мало) в DllMain:

В данном конкретном случае _initptd() вызывается GetModuleHandle("KERNEL32.DLL") функция времени выполнения.

Для справки, вот несколько ссылок о блокировке загрузчика, которые могут быть полезны, независимо от того, есть ли у вас DllMain в наборе:

Документы для DllMain, в которых содержится несколько строгих предупреждений:http://msdn.microsoft.com/en-us/library/ms682583.aspx

И ссылка-фест из «Old New Thing» Рэймонда Чена:

Комментарии:

1. Ах, это имеет огромный смысл для меня, учитывая рассуждения из моего собственного anser. Должно быть, это оно

2. Этот поток был создан в стартовом коде приложения, а не в DLL.

3. @suds: Является ZQCommonStlp ли модуль приложения двоичным? Или приложение загружает DLL? Можете ли вы получить трассировки стека для других потоков, у которых может быть блокировка загрузчика (что-то, по-видимому, происходит)? Возможно, вы зависли от какой-то другой библиотеки DLL.

4. О, я думаю, что Майкл прав. Zqcommon STLP — это dll, от которой зависит мое приложение.

5. Я проверю все DLL-файлы, чтобы увидеть, есть ли какой-либо поток, созданный из DllMain.

Ответ №2:

Ну, он ожидает получения модуля для запущенного исполняемого файла (HMODULE). Возможно, вам захочется проверить, открывали ли вы такой дескриптор, особенно если он заблокирован для совместного чтения.

Возможно, procexp.exe от Sysinternals (Microsoft) могло бы помочь найти заблокированный дескриптор. Или вы можете тщательно изучить любые дескрипторы HMODULE, вызовы LoadLibrary, чтобы найти виновника