5

Я разрабатываю приложение, имеющее один TCP-сервер и несколько UDP-серверов/слушателей. Каждый сервер представляет собой отдельный поток, такой же, как рабочие потоки для установленных TCP-соединений. Я вызываю WSAStartup() в каждом из потоков.Может ли вызов WSAStartup() из нескольких потоков вызвать тупик?

Иногда вызов WSAStartup() висит (он выглядит как тупик для меня). Ниже приведена трассировка стека:

[email protected]() 
    [email protected]() + 0xc bytes 
    [email protected]() + 0x8c bytes 
    [email protected]() + 0x46 bytes 
    [email protected]() + 0x17d bytes 
    [email protected]() + 0x18 bytes 
    [email protected]() + 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 
    [email protected]() + 0xa7 bytes 

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

Мой вопрос: может ли вызвать WSAStartup() из нескольких потоков вызвать этот тупик? Также я проверил, что WSACleanup() вызывается перед тупиком, и это не так. Исполнение никогда не достигает WSACleanup().

Я знаю, что только один вызов WSAStartup должно быть достаточно, но требующие WSAStartup() несколько раз, не должно быть проблемой (MSDN] 1): «Приложение может вызвать WSAStartup несколько раз, если это необходимо получить информацию о структуре WSADATA более одного раза ". Следовательно, я хотел бы установить, вызван ли этот тупик WSAStartup() или чем-то еще.

+0

Это не ответ на ваш вопрос, но вы рассмотреть вопрос об использовании наддува ASIO (http://www.boost.org/doc/libs/1_43_0/doc/html/boost_asio.html)?У меня было намного легче решать такие проблемы, как ваша, с этой библиотекой. – nabulke

+0

Николай, я использовал импульс раньше и как он. Поскольку я начал это приложение с WinSock, я хотел бы разобраться в этом вопросе. Просто любопытно, я думаю :) –

+0

Вы посмотрели на столы вызовов ваших других потоков? –

ответ

2

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

+1

Imho, вопрос гласит, что тема стартера прочитала эту часть MSDN и вместо решения «избежать» проблемы (что, безусловно, является хорошим решением) - он пытается найти основную причину. – Andrey

+0

Это похоже на старую шутку: «Доктор, мне больно, когда я это делаю». «Значит, не делай этого». –

+1

Он должен быть вызван на протекторе, который создает сокет. – rxantos

0

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

+0

Я работаю над автономным приложением, и я использую системные DLL, поэтому у меня нет DLLMain(). Все мои вызовы WSAStartup() относятся к функциям потока: http://msdn.microsoft.com/en-us/library/ms686736(VS.85).aspx PS. вот список дополнительных библиотек: - ws2_32.lib - strsafe.lib - shell32.lib –

+0

Ознакомьтесь с списком DLL, загружаемых в «выпускную» версию вашего приложения (без профайлеров, детекторов утечки , и т.д). Скорее всего, одна из этих DLL - это захват оконных функций. Проводник процессов SysInternals поможет вам многое. – Andrey

0

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

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

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

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

+1

Вы уверены, что это не вызов ** LoadLibrary **? –

+0

Вы правы, я не помню, почему я так думал тогда, но на самом деле может загружать вспомогательные DLL в соответствии с MSDN, поэтому блокировка загрузчика может быть проблемой. Я все еще думаю, глядя на стек, первопричина в ловушке, которая перехватила WSAStartup. – Andrey

3

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

Смежные вопросы