Здравствуйте.
Есть серверное приложение, каждому новому клиенту выделяется свой собственный поток. Испльзуются неблокирующие ассинхронные сокеты из библиотки ws2_32.dll (API, никаких MFC или иных классов), а так же механизм обработки сетевых событий. И вот, иногда возникают моменты, когда при выполнении функций send и, что интересно, closesocket, поток зависает (выход из функции не происходит), процессор выдает загрузку 100%, а серверная часть отказывается принимать новые соединения. При этом все присоединенные клиенты продолжают нормально работать. Создать искусственные условия возникновения ошибки никак не удается, однако прослеживается определенная закономерность: при возрастании количества активных клиентов, увеличивается шанс возникновения такой ситуации (в случае, когда их больше 100, программа не живет и дня).
Однажды все-таки удалось смоделировать одну из ситуаций, которая приводила к зависанию. Клиент отсылал сообщение серверу, после чего соединение внезапно разрывалось со стороны клиента. Эвент, получив уведомление о поступивших данных срабатывал и сервер начинал обработку пакета. Пакет, оказывался, например, устаревшим для текущего протокола и клиенту отправлялось уведомительное сообщение о невозможности обработать пакет. Но так как соединение уже потеряно, при попытке отправить пакет поток повисал на send'е. Но ведь в таких случаях send должен вернуть ошибку? Этот момент решил проверкой, не поступил ли FD_CLOSE перед каждом send'ом. Но проблема до конца все равно не решилась, хотя случаи повисания и стали более редкими.
Пробовал изменить механизм обслуживания: отказался от эвентов, стал использовать циклы и select — проблема не исчезла, даже хуже: случаи участились. Запихал send и closesocket в SEH-блок — проблема не исчезла, однако, с шансом 50/50 она либо тихо аварийно (без сообщения об ошибке) завершалась, либо привычно висла с полной загрузкой процессора.
Перечитал кучу различной информации о сокетах, начиная от MSDN и кончая каким-то официальным описанием — не нашел никакого намека на решение проблемы. Закралось подозрение, что использую, сам того не ведая блокирующие сокеты (хотя в описании указано, что WSAEventSelect автоматически переводит сокет в неблокирующий режим), вручную помечал новый сокет как неблокирующий — непомогло.
Оказавшись в тупике, на всякий случай полностью поменял механизм работы с потоками, пул потоков, перепроверил логику работы с ними... Менял тип приложения (GUI на консоль). Проблема упорно отказывается решаться. Не представляю что еще можно сделать. Если кто-то с подобным тоже встречался...
Тестировалось все это дело на Windows NT 4.0, Windows 2000 Server, Windows 2003. При разработке использовался компилятор MS Visual C++ 6.0 и 7.0 (версию тоже в надежде на чудо менял). Если будут необходимы участки кода — могу предоставить.