2013-11-26 3 views
1

Я работаю с многопоточным встроенным приложением, в котором epoll используется для ввода-вывода в одном из потоков. Я полагаюсь на определенную особенность epoll, которая указывает, что закрытие дескриптора файла автоматически удаляет его из набора epoll (вопрос/ответ 6 в man 7 epoll). В этом случае закрытие дескриптора файла выполняется в том же потоке, который вызывается epoll_wait. Что происходит, так это то, что epoll_wait возвращает событие в дескрипторе файла после того, как оно было закрыто, и программа заканчивается сбоем, поскольку она пытается получить доступ к ресурсам, которые были освобождены при закрытии дескриптора файла. Насколько мне известно, файловый дескриптор нигде не обманут, хотя я не знаю, как его проверить. Я знаю, что нет никаких звонков в fork(), dup(), dup2() или fcntl() с конкретным вариантом dup. Этот конкретный дескриптор файла зарегистрирован в EPOLLOUT, EPOLLIN, EPOLLERR и EPOLLHUP. Он инициируется с помощью уровня. Есть ли какие-либо оговорки в отношении этой функции, о которой никто не знает? Неправильная ли страница руководства? Любая полезная информация, которая может помочь мне отладить проблему? Я знаю, что могу просто удалить дескриптор файла из набора, но я хотел бы знать, почему это происходит.Epoll_wait возвращает события в закрытом дескрипторе файла

+0

События, которые epoll_wait вернули для этого файлового дескриптора, были EPOLLIN, EPOLLHUP и EPOLLERR. – duffsterlp

+0

Вы можете использовать [strace] (http://linux.die.net/man/1/strace), чтобы убедиться, что ваша программа делает то, что, по вашему мнению, делает. Можете ли вы воспроизвести это поведение в простой однопоточной тестовой программе? –

ответ

2

Закрытие дескриптора файла, похоже, не удаляет его из эпохи. Я попробовал это с очень простым примером на 3.12.2. Я склонен называть страницу руководства неправильной или неточной.

То, что я сделал в тесте был:

  • создал сокет TCP
  • обвили его на локальный: 5555
  • набор его слушать
  • создал Epoll
  • добавлен сокет там с hup, err и в
  • спал немного, поэтому я мог бы подключиться к нему с помощью nc
  • закрыл сокет
  • epoll_wait
  • epoll_ctl дель
  • очищены

Ожидание работает, даже если сокет был закрыт, был ли я подключил к нему или нет.

Редактировать: The epoll_ctl_del не удалось, если розетка была закрыта. И, прочитав текущие страницы руководства, кажется, что они на самом деле в порядке. Страница epoll указывает на выбор (2) закрытия закрываемого сокета, и эта страница говорит о том, что поведение не указано.

+0

Для записи, что я делаю на одном сервере, когда соединение закрывается, я удаляю его из epoll явно (и на самом деле флаг epoll для повторного ожидания, если он только что вышел из epoll_wait, который запускается в другой поток), а затем продолжайте закрывать и уничтожать связанные ресурсы. –

+0

Тот факт, что epoll_ctl del работал в вашем примере, очень подозрительно. Сокет либо не закрыт, либо дублирован. Можем ли мы увидеть код? –

+0

Нашли код. Конечно, 'epoll_ctl_del' не работает.Я сделал флаг «doclose» в моей тестовой программе, чтобы проверить возвращаемые значения ожидания epoll с закрытием сокета и без него, и я, должно быть, взял «del work» из прогона без закрытия, когда он, конечно, работает. –

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