我在epoll_wait()
和侦听器套接字之间看到以下交互。用于创建侦听器套接字的事件序列是:
socket()
bind()
fcntl()
并设置为非阻止epoll_ctl()
和EPOLL_CTL_ADD
EPOLLET | EPOLLONESHOT | EPOLLIN
listen()
有后台线程为此套接字调用epoll_wait()
和其他线程,如果在步骤4和5之间发生这种情况,则会收到侦听器套接字的EPOLLHUP
事件。将序列更改为:
socket()
bind()
fcntl()
并设置为非阻止listen()
epoll_ctl()
和EPOLL_CTL_ADD
EPOLLET | EPOLLONESHOT | EPOLLIN
醇>
解决了这个问题,但是现在我看到了连接失败的虚假失败,但没有收到侦听器套接字的EPOLLIN
事件。
我理解可以选择使用电平触发模式,但我想让它适用于边缘触发模式。
关于问题可能是什么想法?
答案 0 :(得分:1)
EPOLLONESHOT
的语义是,epoll_wait()
为某些描述符提取通知后,您必须使用epoll_ctl()
致电EPOLL_CTL_MOD
至在该描述符上重新启用通知。因此,您可能会因为EPOLLONESHOT
已禁用被动/侦听套接字上的通知而丢失连接。 (一般情况下,除了特殊情况外,EPOLLONESHOT
此外,对于非阻塞边缘触发的语义,在通知侦听套接字已准备好输入时,需要在循环中调用accept()
,直到报告EAGAIN
错误。仅调用accept()
一次可能会在队列中留下其他连接,此外,在将全新连接添加到该队列之前,不会发生另一个边缘触发的EPOLLIN
事件。 (也就是说,假设未指定EPOLLONESHOT
,或者每次下次调用epoll_wait()
之前重新启用描述符。)
ADDENDUM 消除EPOLLONESHOT当然值得一试。你为什么还需要它?