У меня есть следующий отрывок кода (сильно отредактированный, чтобы удалить несущественные детали), который не срабатывает при редком и конкретном множестве обстоятельств.Как обновить события epoll после epoll_wait?
struct epoll_event *events = calloc(MAXEVENTS+1, sizeof(struct epoll_event));
struct sockaddr_in in_addr;
socklen_t in_len = sizeof in_addr;
while(1)
{
int n = epoll_wait(efd,events, MAXEVENTS, -1);
for(int i=0; i<n; i++)
{
struct epoll_event *evI = &events[i];
uint64 u64 = evI->data.u64;
int type = u64>>32, fd=u64, fdx = fd;
if(type == -1)
{
while((fd = accept4(fdx, &in_addr, &in_len, SOCK_NONBLOCK|SOCK_CLOEXEC))>-1)
{
setNew_Connection(efd, fd);
storeAddrPort(fd, &in_addr, &in_len);
}
}
else
{
if(evI->events&(EPOLLERR|EPOLLHUP|EPOLLRDHUP)){closeConnection(fd);}
if(evI->events&EPOLLOUT) //process out data stuff
else if(evI->events&EPOLLIN) //process in data stuff and possibly close a different connection.
}
}
}
слушающих сокетов различаются по -1
в верхней части evI->data.u64
setNew_Connection
делает к Epoll т.д.
EPOLLET
используется обычный прием такие вещи, как добавление нового сокета.
Теперь все работает прекрасно за исключением следующих обстоятельств он не потому, что events
обновляется только в epoll_wait
так укупорочное соединение не влияет на n
события, пока после возвращения к началу цикла while(1)
.
epoll_wait
разблокирован с 3 событиями в очереди событий в таблице событий.- Первое событие (n = 0) - это входящие данные, после которых код решает закрыть соединение (например, дескриптор файла 8), поскольку он больше не нужен.
- Второе событие (n = 1) - это новое новое соединение.
accept4
назначает fd: 8, поскольку он недавно стал доступен.setNew_Connection
добавляет его в список epoll. - Третье событие - это входящие данные для соединения, закрытого на этапе 2. i.e fd: 8, но оно больше недействительно, поскольку исходное соединение fd: 8 было закрыто, а текущий fd: 8 - для другого соединения.
Надеюсь, я правильно объяснил проблему. Проблема в том, что события в очереди в таблице events
не обновляются, когда соединение закрывается до тех пор, пока код не вернется к epoll_wait
. Как я могу кодировать эту проблему?
Вы можете отметить соединение будет закрыто, и сделать петлю закрытия после того, как обработчик событий. –