监听器套接字上的epoll_wait()和虚假失败

时间:2013-01-08 18:08:51

标签: sockets listener epoll

我在epoll_wait()和侦听器套接字之间看到以下交互。用于创建侦听器套接字的事件序列是:

  1. 致电socket()
  2. 致电bind()
  3. 致电fcntl()并设置为非阻止
  4. 使用epoll_ctl()EPOLL_CTL_ADD
  5. 致电EPOLLET | EPOLLONESHOT | EPOLLIN
  6. 致电listen()
  7. 有后台线程为此套接字调用epoll_wait()和其他线程,如果在步骤4和5之间发生这种情况,则会收到侦听器套接字的EPOLLHUP事件。将序列更改为:

    1. 致电socket()
    2. 致电bind()
    3. 致电fcntl()并设置为非阻止
    4. 致电listen()
    5. 使用epoll_ctl()EPOLL_CTL_ADD
    6. 致电EPOLLET | EPOLLONESHOT | EPOLLIN

      解决了这个问题,但是现在我看到了连接失败的虚假失败,但没有收到侦听器套接字的EPOLLIN事件。

      我理解可以选择使用电平触发模式,但我想让它适用于边缘触发模式。

      关于问题可能是什么想法?

1 个答案:

答案 0 :(得分:1)

EPOLLONESHOT的语义是,epoll_wait()为某些描述符提取通知后,您必须使用epoll_ctl()致电EPOLL_CTL_MOD在该描述符上重新启用通知。因此,您可能会因为EPOLLONESHOT已禁用被动/侦听套接字上的通知而丢失连接。 (一般情况下,除了特殊情况外,EPOLLONESHOT

此外,对于非阻塞边缘触发的语义,在通知侦听套接字已准备好输入时,需要在循环中调用accept(),直到报告EAGAIN错误。仅调用accept()一次可能会在队列中留下其他连接,此外,在将全新连接添加到该队列之前,不会发生另一个边缘触发的EPOLLIN事件。 (也就是说,假设未指定EPOLLONESHOT,或者每次下次调用epoll_wait()之前重新启用描述符。)

ADDENDUM 消除EPOLLONESHOT当然值得一试。你为什么还需要它?