2013-06-12 3 views
1

У меня проблема с моей многопоточной сетевой серверной программой.Функция unix accept() возвращает тот же самый дескриптор файла

У меня есть основная тема, которая прослушивает новые клиентские соединения. Я использую Linux epoll для получения уведомлений о событиях ввода-вывода. Для каждого входящего события я создаю поток, который принимает() новое соединение и назначает ему fd. При большой загрузке может произойти, что один и тот же fd назначается дважды, что приводит к сбою моей программы.

Мой вопрос: как система может назначить fd, который все еще используется другим потоком?

Спасибо,

+0

Возможный дубликат [C: epoll и многопоточность] (http://stackoverflow.com/questions/4687626/c-epoll-and-multithreading) – Nick

ответ

3

Предположительно есть состояние гонки здесь - но не видя кода это трудно диагностировать.

Вам будет лучше: accept в главной теме, а затем передать принятый сокет в новый поток.

Если вы передадите свой слуховой сокет в новый поток, а затем выполните прием - вы попадете в состояние гонки.

Для получения дополнительной информации Вы можете посмотреть здесь: https://stackoverflow.com/a/4687952/516138

И this является хорошим фоном на сетевой эффективности (хотя, возможно, немного устарели).

+0

Хорошо, основываясь на том, что вы сказали, у меня есть два решения моей проблемы , Первый - это «принять» в основном потоке, а затем передать назначенный fd новому рабочему потоку. Второй - иметь выделенный поток для каждого цикла epoll. Одно из этих двух решений может решить проблему моего состояния гонки. Есть ли какая-либо документация где-нибудь, чтобы получить более подробное описание epoll и параллелизма? –

+0

Третий вариант и выбор, который я бы сделал, если бы я писал сетевое приложение на C++ с нуля, будут использовать [ASIO] (http://think-async.com/) (или [Boost.Asio] (http : //www.boost.org/libs/asio)). – Nick

+0

Вы правы. Я тоже об этом думал. благодаря –

0

Вы должны позвонить accept() в тот же поток, который вы вызываете epoll(). В противном случае вы предлагаете условия гонки.

0

Дескрипторы файлов изменяются в соответствии с «за каждый процесс». Это означает, что они уникальны для каждого процесса. Это означает, что несколько потоков могут совместно использовать одни и те же дескрипторы файлов в одном и том же процессе.

Наличие accept syscall, возвращающее один и тот же дескриптор файла внутри одного процесса, является очень сильным признаком того, что некоторые из ваших потоков закрывают предыдущую «версию» повторяющегося файлового дескриптора.

Проблем, подобных этому, может быть сложно отлаживать в сложном программном обеспечении. Способ определить, что в системе Linux используется команда strace. Можно запустить strace -f -e trace=close,accept4,accept,pipe,open <your program>. Это приведет к выходу на ваш экран соответствующих системных вызовов, указанных в команде, вместе с тем, какой поток вызывает ее.

Смежные вопросы