Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/ruby-on-rails-4/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sockets 侦听器套接字上的epoll_wait()和虚假故障_Sockets_Listener_Epoll - Fatal编程技术网

Sockets 侦听器套接字上的epoll_wait()和虚假故障

Sockets 侦听器套接字上的epoll_wait()和虚假故障,sockets,listener,epoll,Sockets,Listener,Epoll,我看到了epoll\u wait()和侦听器套接字之间的以下交互。创建侦听器套接字的事件顺序为: 调用套接字() 调用bind() 调用fcntl()并设置为非阻塞 使用epoll\u ctl\u ADD和EPOLLET | epolleneshot | EPOLLIN调用epoll\u ctl() 调用listen() 有后台线程为此套接字和其他套接字调用epoll\u wait(),如果在步骤4和步骤5之间碰巧这样做,则会收到侦听器套接字的EPOLLHUP事件。将序列更改为: 调用套接字()

我看到了
epoll\u wait()
和侦听器套接字之间的以下交互。创建侦听器套接字的事件顺序为:

  • 调用套接字()
  • 调用
    bind()
  • 调用
    fcntl()
    并设置为非阻塞
  • 使用
    epoll\u ctl\u ADD
    EPOLLET | epolleneshot | EPOLLIN调用
    epoll\u ctl()
  • 调用
    listen()
  • 有后台线程为此套接字和其他套接字调用
    epoll\u wait()
    ,如果在步骤4和步骤5之间碰巧这样做,则会收到侦听器套接字的
    EPOLLHUP
    事件。将序列更改为:

  • 调用套接字()
  • 调用
    bind()
  • 调用
    fcntl()
    并设置为非阻塞
  • 调用
    listen()
  • 使用
    epoll\u ctl\u ADD
    EPOLLET | epolleneshot | EPOLLIN调用
    epoll\u ctl()
  • 解决了这个问题,但现在我看到了虚假的故障,即建立了连接,但没有为侦听器套接字接收到
    EPOLLIN
    事件

    我知道有人可以选择使用水平触发模式,但我想让这个工作的边缘触发模式


    有什么想法吗?

    epolleneshot
    的语义是,一旦某个描述符的通知被
    epoll\u wait()
    拉出来,您就必须调用
    epoll\u ctl()
    epoll\u MOD
    来重新启用该描述符上的通知。因此,您可能会因为
    epolonneshot
    已禁用被动/侦听套接字上的通知而丢失连接。(一般来说,
    epolonneshot
    不应使用,除非特殊情况;它不是自动添加到代码中的样板或伏都教。)

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


    附录消除埃普洛内肖特当然值得一试。你为什么还需要它

    谢谢你的回复。我应该澄清,这种虚假故障的场景是第一个也是唯一一个连接到侦听器端口的连接。因此,侦听器描述符只经历过一次EPOLL_CTL_ADD,而EPOLLONESHOT还没有出现在图片中。作为一个实验,我从边缘触发改为水平触发,仍然看到虚假的失败。查看最近的linux内核讨论,似乎有一个ePloloneshot bug可能是导致。。。您是否尝试过第二次连接,以查看这是否会唤醒套接字并导致两次成功的accept()?这表明,如果连接已在EPOLL_CTL_ADD点的侦听队列中(不太可能,但您永远不知道),则边缘触发的通知将不起作用。无论如何,您可以通过立即调用accept()来解决这个问题(因为它不会阻塞)。但是,一般来说,边缘触发语义对于读/输入端并不总是一个好主意。作为另一个实验,我也消除了epolonneshot,但仍然看到了虚假的失败。这是相当令人费解的。在我看过的其他代码示例中,listen()调用是在将侦听器描述符添加到epoll集合之后进行的。但是这些示例没有并发的epoll_wait()调用。我是这样做的,并且在将描述符添加到epoll集合之前必须先移动listen()调用,以避免接收EPOLLHUP事件。我从未见过在通过listen()使套接字变为被动之前将套接字添加到轮询集合的代码。即使是联机手册页的副本,例如,也会起到相反的作用。你有链接吗?