1

这是问题 14221339 的后续内容。

我有一个在epoll_wait()循环内运行的线程池。

一个外部线程调用epoll_ctl()并添加一个侦听器套接字

(EPOLLET | EPOLLONESHOT | EPOLLIN).

当线程池只有一个线程时,它会间歇性地无法接收EPOLLIN第一次(也是唯一一次)连接尝试的事件。如果我将线程池增加到两个,它几乎总是无法接收到EPOLLIN事件。

我的理解是 epoll API 是线程安全的,但这种观察似乎表明并非如此。

4

1 回答 1

7

With edge-triggered semantics, an incorrect sequence of calls can result in a race condition. There are three system calls involved:

  1. epoll_ctl() to activate notifications (and reactivate if EPOLLONESHOT is used).
  2. epoll_wait() to receive notifications.
  3. system input: read()/recv()/accept() in a loop until error EAGAIN.

If executed (repeatedly) in this order, a race between #3 and #1 is possible: when the input event in the kernel occurs after EAGAIN has been returned but before epoll_ctl() can be acted on. In general, the re-activation needs to be done before the I/O.

  1. epoll_ctl() to activate notifications (and reactivate if EPOLLONESHOT is used).
  2. system input: read()/recv()/accept() in a loop until error EAGAIN.
  3. epoll_wait() to receive notifications.

(Obviously, the I/O needs to be non-blocking.)

于 2013-01-09T15:53:36.540 回答