Может ли вызов WSAStartup () из нескольких потоков вызвать тупик? - PullRequest
5 голосов
/ 05 августа 2010

Я занимаюсь разработкой приложения, которое имеет один 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 ]

4 голосов
/ 04 октября 2013

Функция WSAStartup обычно приводит к загрузке вспомогательных DLL-протоколов конкретного протокола.В результате функция WSAStartup не должна вызываться из функции DllMain в прикладной DLL.Это может привести к взаимоблокировке.Dllmain вызывается в критической секции загрузчика DLL, которая является основной причиной этого тупика.
Для более подробной информации: http://msdn.microsoft.com/en-us/library/windows/desktop/ms742213%28v=vs.85%29.aspx

2 голосов
/ 05 августа 2010

Вам вообще не нужно звонить WSAStartup() несколько раз. Один раз на программу в порядке.

1 голос
/ 05 августа 2010

Я думаю, что Люк прав.Вы не можете вызывать WSAStartup () в DllMain () или в инициализаторах глобальных / статических переменных.Измените свой код, чтобы этого не произошло.

0 голосов
/ 06 августа 2010

WSAStartup на самом деле не приводит к LoadLibrary любого вида, поэтому я не чувствую, что это loader lock случай.

Вместо этого очевидно, что Windows API в вашем случае оказывается в ловушке (термин trap здесь лучше, поскольку hook имеет другое значение в Windows).

Таким образом, я считаю, что проблема не в одновременном использовании WSAStartup , а в побочных эффектах сторонних ловушек по сравнению с оригинальными функциями Windows API в вашем процессе. Я думаю, вам нужно очистить вашу среду от любого внешнего воздействия (API-ловушки с вашей стороны или от антивирусного программного обеспечения, что угодно).

Кстати, убедитесь, что каждый ваш поток предоставляет WSAStartup свою отдельную копию выходного параметра WSADATA

...