Может ли вызов WSAStartup() из нескольких потоков вызвать тупик?
Я разрабатываю приложение, которое имеет один TCP-сервер и несколько UDP-серверов / слушателей. Каждый сервер является отдельным потоком, таким же, как рабочие потоки для установленных соединений TCP. Я вызываю WSAStartup() в каждом из потоков.
Иногда вызов WSAStartup() зависает (для меня это похоже на тупик). Вот трассировка стека:
ntdll.dll!_KiFastSystemCallRet@0()
ntdll.dll!_ZwWaitForSingleObject@12() + 0xc bytes
ntdll.dll!_RtlpWaitForCriticalSection@4() + 0x8c bytes
ntdll.dll!_RtlEnterCriticalSection@4() + 0x46 bytes
ntdll.dll!_LdrpGetProcedureAddress@20() + 0x17d bytes
ntdll.dll!_LdrGetProcedureAddress@16() + 0x18 bytes
kernel32.dll!_GetProcAddress@8() + 0x3e bytes
vld.dll!03203723()
[Frames below may be incorrect and/or missing, no symbols loaded for vld.dll]
ws2_32.dll!CheckForHookersOrChainers() + 0x22 bytes
ws2_32.dll!_WSAStartup@8() + 0xa7 bytes
Этот тупик возникает во время инициализации. Я вижу, что TCP-сервер запущен и что установлено одно TCP-соединение, а запущен только один из UDP-серверов. Трассировка стека происходит от функции, которая должна инициировать остальные UDP-серверы. Я предполагаю, что в то время как я пытаюсь инициировать UDP-сервер и вызывать WSACStartup(), другой шаг обрабатывает другую операцию сокета, например, новое TCP-соединение, и также вызывает WSAStartup()?
Мой вопрос заключается в том, может ли вызов WSAStartup() из нескольких потоков вызвать эту тупиковую ситуацию? Также я проверил, вызывается ли WSACleanup() до тупика, и это не так. Выполнение никогда не достигает ни одного из WSACleanup().
Мне известно, что достаточно одного вызова WSAStartup, но вызов WSAStartup() несколько раз не должен вызывать проблем (MSDN] 1): "Приложение может вызывать WSAStartup более одного раза, если ему необходимо получить информацию о структуре WSADATA. больше чем единожды." Следовательно, я хотел бы установить, вызван ли этот тупик WSAStartup() или чем-то еще.
4 ответа
Функция WSAStartup обычно приводит к загрузке вспомогательных DLL-библиотек. В результате функция WSAStartup не должна вызываться из функции DllMain в DLL-библиотеке приложения. Это может привести к взаимоблокировке. Dllmain вызывается в критической секции загрузчика DLL, которая является основной причиной этого тупика.
Для получения дополнительной информации: http://msdn.microsoft.com/en-us/library/windows/desktop/ms742213%28v=vs.85%29.aspx
Вам не нужно звонить WSAStartup()
несколько раз на всех. Один раз на программу в порядке.
Я думаю, что Люк прав. Вы не можете вызывать WSAStartup() в DllMain() или в инициализаторах глобальных / статических переменных. Измените свой код, чтобы этого не произошло.
WSAStartup на самом деле не приводит к LoadLibrary любого рода, поэтому я не чувствую, что это loader lock
дело.
Вместо этого, очевидно, что Windows API находится в ловушке в вашем случае (термин trap
здесь лучше, потому что hook
имеет другое значение в Windows).
Таким образом, я считаю, что проблема не в одновременном использовании WSAStartup, а в побочных эффектах сторонних ловушек по сравнению с оригинальными функциями Windows API в вашем процессе. Я думаю, вам нужно очистить вашу среду от любого внешнего воздействия (API-ловушки с вашей стороны или от антивирусного программного обеспечения, что угодно).
Кстати, убедитесь, что каждый ваш поток предоставляет WSAStartup свою отдельную копию выходного параметра WSADATA