Неверный дескриптор файла, закрывающий Boost-сокет - PullRequest
4 голосов
/ 12 октября 2011

Я использую Boost 1.45 ASIO для обработки некоторых соединений с сокетами в приложении, которое работает как на Windows, так и на Mac.В Windows следующий код не вызывает никаких ошибок, и мои сокеты закрыты чисто.На Mac, однако, и завершение работы, и (если я закомментировал это) функции закрытия дают мне ошибки «Bad file descriptor».До тех пор, пока я не вызову этот код, сокеты работают нормально.Но как только я вызываю shutdown или close, я получаю ошибку.Есть идеи, что может происходить?

if(socket.is_open())
{
    socket.shutdown(socket.both);
    socket.close();
}

Ответы [ 3 ]

7 голосов
/ 18 октября 2011

«Неверный дескриптор файла» на close обычно означает, что дескриптор уже закрыт. Часто это происходит из-за ошибки двойного закрытия в каком-то совершенно не связанном разделе программы.

Такая ошибка может быть заразной. Если ваша программа закрывает один и тот же дескриптор дважды, и он тем временем перераспределяется, вторая close закроет дескриптор некоторого несвязанного объекта из-под них. И затем, когда этот объект закрывает свой дескриптор, он может фактически закрывать еще один дескриптор другого объекта ... И так далее, пока последний в строке не получит ошибку "неверный дескриптор файла".

Это побочный эффект (а) дескрипторов, являющихся глобальным состоянием, и (б) требования Unix, что любой вызов open / socket / etc. назначить неиспользуемый дескриптор с наименьшим номером.

Единственный способ отладки, который я знаю, - это мониторинг создания и уничтожения всех файловых дескрипторов с помощью такого инструмента, как strace (в Linux) или dtrace (в Mac). (Ну, может быть, не единственный способ. Однажды я написал хитрый LD_PRELOAD хак, чтобы перехватывать каждый вызов open и close, чтобы выяснить, какой поток дважды закрывал их дескриптор, потому что второе закрытие было уничтожением дескриптора используется другим потоком ...)

Удачи.

2 голосов
/ 18 октября 2011
if(socket.is_open())
{
    socket.shutdown(socket.both);
    socket.close();
}

Если у вас нет веских причин для этого, я предлагаю позволить деструктору socket::~socket() закрыть базовый собственный дескриптор файла.Если вас беспокоит утечка дескрипторов, используйте инструмент, подобный valgrind , для анализа вашей программы.

0 голосов
/ 18 октября 2011

У меня была такая же проблема: в Windows все было нормально, а в Linux возникало исключение в зависимости от состояния сокета IIRC.

Альтернативой ответу Сэма является использование фиктивного кода ошибки, чтобы молча игнорировать исключение, если оно происходит.См. Перегрузки close и shutdown в документации asio.

...