У epoll есть проблемы с потоками?
Это продолжение вопроса 14221339.
У меня есть пул потоков, который работает внутри epoll_wait()
петля.
Внешний поток вызывает epoll_ctl()
и добавляет сокет слушателя с
(EPOLLET | EPOLLONESHOT | EPOLLIN)
,
Когда пул потоков имеет только один поток, он периодически не может получить EPOLLIN
событие для первой (и единственной) попытки подключения. Если я увеличу пул потоков до двух, он почти всегда не получит EPOLLIN
событие.
Насколько я понимаю, API epoll является поточно-ориентированным, но, похоже, это наблюдение указывает на обратное.
1 ответ
При семантике, инициируемой ребром, неправильная последовательность вызовов может привести к состоянию гонки. Здесь задействованы три системных вызова:
- epoll_ctl() для активации уведомлений (и повторной активации, если используется EPOLLONESHOT).
- epoll_wait () для получения уведомлений.
- системный ввод: чтение ()/recv()/accept() в цикле до появления ошибки EAGAIN.
Если выполняется (многократно) в этом порядке, возможна гонка между #3 и #1: когда событие ввода в ядре происходит после того, как EAGAIN был возвращен, но до того, как epoll_ctl() может быть задействована. Как правило, повторную активацию необходимо выполнить до ввода-вывода.
- epoll_ctl() для активации уведомлений (и повторной активации, если используется EPOLLONESHOT).
- системный ввод: чтение ()/recv()/accept() в цикле до появления ошибки EAGAIN.
- epoll_wait () для получения уведомлений.
(Очевидно, что ввод / вывод должен быть неблокирующим.)