попробую сформулировать проблему:
есть приложение-сервер (с клиентом никаких проблем нет).
сервер в зависимости от режима работы (обычное приложение или NT сервис) запускает нужную dll в нужном режиме.
так вот реализация работы с сокетами (TCP соединение с клиентами) в сервере находится в dll.
в dll имеется класс с конструктором и деструктором, понятное дело, в которых вызываются WSAStartup и WSACleanup соответственно.
в этой же dll имеется еще один класс работы с другим сокетом (UDP соединение с внешней железякой — коммутационная станция КСМ-400 через Ethernet).
там такой же почти конструктор и деструктор с теми же WSAStartup и WSACleanup (это для того чтоб можно этот класс в других приложениях применять).
ну и вобщем все это работает и взаимодействует между собой. Работает все прекрасно.
Проблема заключается в том, что при закрытии сервера (при вызове деструкторов, и надо сказать что выше описанные классы являются базовыми для некоего потомка через множественное наследование, то есть деструкторы вызываются один за другим сразу) происходит удачное выполнение первого вызова WSACleanup и блокируется второй вызов WSACleanup.
При этом первые два вызова WSAStartup из конструкторов проходят очень спокойно (нормально).
Вобщем схема такая :
1. WSAStartup
2. WSAStartup
3. создаются сокеты
4. какая то работа в потоках с сокетами
5. закрываются сокеты
6. WSACleanup
7. WSACleanup
из-за этого трабла в среднем на четвертое-пятое закрывание приложения происходит deadlock потока (там где деструкторы).
то есть иногда все нормально закрывается, а иногда просто заговор какой-то. В WSACleanup входит и замирает.
В чем может крыться проблема ???
VC++6.0 SP5 (NOT MFC,ATL or other libs) only Win32API
Windows2000 Pro SP4 eng (WS2_32.DLL)
Здравствуйте, pankov, Вы писали:
P>из-за этого трабла в среднем на четвертое-пятое закрывание приложения происходит deadlock потока (там где деструкторы). P>то есть иногда все нормально закрывается, а иногда просто заговор какой-то. В WSACleanup входит и замирает. P>В чем может крыться проблема ???
If an application needs to quit while a blocking call is outstanding, the application must first cancel the blocking call with WSACancelBlockingCall then issue the WSACleanup call once control has been returned to the application.
это я читал собственно так оно и сделано...
B>Вот ещё MSDN: B>
B>If an application needs to quit while a blocking call is outstanding, the application must first cancel the blocking call with WSACancelBlockingCall then issue the WSACleanup call once control has been returned to the application.
и с MSDNом я тоже дружу . WSACancelBlockingCall относится к старой реализации винсокетов. Пробовал я делать этот вызов, но помочь он ничем не смог...
Наблюдается следующая картинка :
я вызвал shutdown и closesocket для всех сокетов, но иногда потоки в которых проходят прослушивание, чтение и запись не завершаются. А завершаться они должны по принципу : возвратилась ошибка, выйти из потока. Видимо не всегда происходят выходы. Забыл я еще упомянуть о факте работы rpc в сервере. Возможно rpc как то влияет и блокирует WSACleanup. Старый добрый MSDN не содержит к сожалению решений подобных ситуаций...
Может прибиение rpc как то блокирует сокеты приложения ??? Но почему первый WSACleanup проходит хорошо (он кстати пока не выгружает ws2_32.dll, а только лишь декремент выполняет), а второй блокируется (вот этот и выполняет выгрузку ws2_32.dll). Стоит отметить, что ранее я прибивал потоки через TerminateThread, но потом следуя рекомендации Дж.Рихтера сделал выход из потока внутри через rerurn. Раньше это все работало без rpc. Но пришла беда на нашу землю и .... о чем это я ?
P>Наблюдается следующая картинка :
P>я вызвал shutdown и closesocket для всех сокетов, но иногда потоки в которых проходят прослушивание, чтение и запись не завершаются. А завершаться они должны по принципу : возвратилась ошибка, выйти из потока. Видимо не всегда происходят выходы. Забыл я еще упомянуть о факте работы rpc в сервере. Возможно rpc как то влияет и блокирует WSACleanup. Старый добрый MSDN не содержит к сожалению решений подобных ситуаций...
P>Может прибиение rpc как то блокирует сокеты приложения ??? Но почему первый WSACleanup проходит хорошо (он кстати пока не выгружает ws2_32.dll, а только лишь декремент выполняет), а второй блокируется (вот этот и выполняет выгрузку ws2_32.dll). Стоит отметить, что ранее я прибивал потоки через TerminateThread, но потом следуя рекомендации Дж.Рихтера сделал выход из потока внутри через rerurn. Раньше это все работало без rpc. Но пришла беда на нашу землю и .... о чем это я ?
скорее всего ошибка где-то у Вас в приложении
по shutdown() и closesocket() должны вывалится все блокирующие send() и recv()
по closesocket() должны вывалится все блокирующие accept()
дождитесь завершения рабочих потоков WaitForSingleObject() WaitForMultipleObjects()
потом уже закрывайте winsock, лучше это делать не в каждом объекте, все-таки,
хотя если объект статический и живет все время работы программы, то можно.
кстати говоря, не всегда, к примеру, recv() вернет ошибку, может вернуть и EOF
(т.е. return не SOCKET_ERROR а 0 — тоже значит партнер закрылся)
Здравствуйте, Аноним, Вы писали:
А>скорее всего ошибка где-то у Вас в приложении
А>по shutdown() и closesocket() должны вывалится все блокирующие send() и recv() А>по closesocket() должны вывалится все блокирующие accept() А>дождитесь завершения рабочих потоков WaitForSingleObject() WaitForMultipleObjects() А>потом уже закрывайте winsock, лучше это делать не в каждом объекте, все-таки, А>хотя если объект статический и живет все время работы программы, то можно.
А>кстати говоря, не всегда, к примеру, recv() вернет ошибку, может вернуть и EOF А>(т.е. return не SOCKET_ERROR а 0 — тоже значит партнер закрылся)
Ошибка была в том, что паралельно еще механизм RPC использовался (тама тоже сокеты как будто бы)
Вобщем, это дело блокирует каким то образом WSACleanup