WSACleanup и atExit

Можно ли зарегистрировать WSACleanup через функцию atExit? У нас есть несколько приложений, которые могут завершать работу в разных точках кода, поэтому мы хотели бы избежать размещения WSACleanup везде через код. В настоящее время мы вызываем WSAStartup / WSACleanup через DllMain, поскольку у нас есть dll, который используется всеми этими приложениями. Однако Microsoft строго рекомендует не использовать WSAStartup / WSACleanup через DllMain, поскольку это может привести к взаимоблокировкам. Мы можем переместить WSAStarup из DllMain и вызвать его в одной точке кода для всех приложений, прежде чем они получат доступ к библиотеке сокетов Windows. И, как только мы вызываем WSAStartup, мы хотели бы использовать функцию atExit для регистрации вызова WSACleanup. У кого-нибудь есть опыт с этим подходом? Спасибо!

3 ответа

Если у вас многопоточное приложение, а некоторые потоки все еще подключены, приложениям на другом конце может не понравиться способ завершения соединения. Поэтому предпочтительно завершить все коммуникации упорядоченным образом до завершения main(), и когда вы это сделаете, вы также можете вызвать WSACleanup.

Я согласен, что подход RAII является благоприятным.

Однако предупреждающее слово: atExit, смешанный с dll и дескрипторами, разбит на окнах. К сожалению, это также влияет на RAII, поскольку это реализуется с помощью обработчиков atExit в среде выполнения C++.

Порядок, в котором обработчики atexit вызываются в windows:

  1. где-то вызывается выход или main() выходит из области видимости
  2. Вызваны обработчики atexit, определенные в процессе.
  3. все ручки уничтожены.
  4. Вызваны обработчики atexit, определенные в dll.

Не имеет значения, регистрируются ли обработчики atexit в dll до того, как обработчики в процессе, сначала вызываются обработчики процесса, а дескрипторы уничтожаются до вызова обработчиков dll. Это приводит к исключениям win32, когда вызывается код очистки, поскольку все дескрипторы, принадлежащие dll, больше не действительны.

Это влияет на код, который содержит дескрипторы потоков, мьютексов, файлов, сокетов и т. Д. Если они размещены в dll, то их необходимо очистить перед вызовом exit или вообще не вызывать.

Кстати, я не против окна, если я ошибаюсь или кто-то знает, как обойти это, я хотел бы знать, так как это причиняет мне невыразимую боль при очистке приложения. Я понял, что это отладка обработки выхода во время выполнения C++ после получения исключений win32 при выходе из приложения.

Мне пришлось удалить все звонки, чтобы выйти из моего кода. Я теперь гарантировал, что никакие статические данные в dll не управляют дескриптором. Все статические маркеры управляются объектами, которые разрушаются, когда main выходит из области видимости.

Ну, я думаю, atExit не следует использовать. Вы должны следовать RAII-принципу обертывания инициализации и уничтожения библиотеки сокетов в классе.

Другие вопросы по тегам