Как обнаружить неверный FD / дескриптор - PullRequest
4 голосов
/ 21 ноября 2011

У меня есть серверное приложение, которое обрабатывает сетевых клиентов с асинхронным вводом-выводом. Клиентские соединения принимаются, затем добавляются в набор дескрипторов, который можно отслеживать с помощью poll / epoll / select / etc. Я использую библиотеку apache APR apr_pollset_poll () для проверки дескрипторов, которые могут быть прочитаны или записаны. Это использует epoll / poll / select / etc внутри, в зависимости от платформы.

Проблема заключается в том, что каким-то образом один из дескрипторов сокетов поврежден, и apr_pollset_poll возвращает значение errno 10038, которое является WSAENOTSOCK: была предпринята попытка выполнить операцию с чем-то, что не является сокетом. К сожалению, это приводит к тому, что мое приложение вообще перестает работать, вместо того, чтобы просто разорвать соединение с конкретным клиентом. Если бы я мог как-то игнорировать или удалить этот сокет из набора дескрипторов, то он мог бы продолжать функционировать и правильно читать / записывать другие сокеты. Я знаю, что должен найти основную причину, которая приводит к повреждению сокета, но мне нужен обходной путь безотказности.

Как только дескрипторы добавлены в набор опросов, они затем обрабатываются ОС / ядром, и я не вижу способа получить их, чтобы иметь возможность повторять их. Сохранение их также в моем собственном списке, вероятно, создало бы другие проблемы в дальнейшем, потому что при закрытии сокета мне нужно было бы как-то их очистить, что происходит автоматически для набора опросов в ядре.

Есть предложения?

Ответы [ 2 ]

2 голосов
/ 21 ноября 2011

Звучит ужасно, но это чрезвычайная ситуация, когда это происходит. Итак, я предлагаю просмотреть все дескрипторы в вашем рабочем наборе опросов и попытаться выполнить операцию с этим дескриптором, которая вызовет эту ошибку, если дескриптор фальшивый. Например, вы можете создать новый временный набор опросов и попробовать неблокирующую операцию опроса с нулевым тайм-аутом и посмотреть, сможете ли вы получить ошибку.

Если у вас в наборе опросов больше, чем, скажем, дюжина дескрипторов, вы можете рассмотреть бинарный поиск вместо одноразового подхода. Вы можете поместить половину своих дескрипторов во временный набор опросов, а затем выполнить операцию. Если это не удается, вы знаете, что у вас есть фиктивный дескриптор в наборе, который вы пробовали; разделите на две части и попробуйте снова; если он не потерпит неудачу, вы можете предположить, что фиктивный дескриптор находится в другом наборе, и вы можете либо подтвердить, что другая половина не удалась, либо предположить, что это произойдет, и разделить остаток на две части и повторить попытку. Продолжайте, пока не изолируете один неисправный дескриптор. Очевидно, что если у вас есть несколько фиктивных дескрипторов, а не один, вам, возможно, придется повторить процесс несколько раз.

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

0 голосов
/ 24 ноября 2011

Оказалось, что я выполняю close () для дескриптора сокета, который опрашивается в другом потоке, и реализация pollset, основанная на select (), не любит этого. С другой стороны, можно было бы изменить код библиотеки apr, чтобы он возвращал дескриптор, когда select обнаруживает недопустимый сокет, или он может даже автоматически удалить его.

...