epoll:它会悄悄地删除 fds 吗?

Epoll: does it silently remove fds?

我通读了 libev's source code 并偶然发现了这条评论:

a) epoll silently removes fds from the fd set. as nothing tells us that an fd has been removed otherwise, we have to continually "rearm" fds that we suspect might have changed (same problem with kqueue, but much less costly there).

我一直在一些现代 linux 内核上使用 epoll(直接使用系统调用)进行一些测试,但我无法重现它。我没有发现 "silently disappearing fds" 有任何问题。有人可以对此进行详细说明并告诉我它是否仍然是一个问题吗?

这是相当模糊的文本,但我想这只是如果描述符在其他地方是 closed,它会被默默地从集合中删除。来自 Linux 联机帮助页,epoll(7):

Q6 Will closing a file descriptor cause it to be removed from all epoll sets automatically?

A6 Yes, but be aware of the following point. A file descriptor is a reference to an open file description (see open(2)). Whenever a descriptor is duplicated via dup(2), dup2(2), fcntl(2) F_DUPFD, or fork(2), a new file descriptor refer‐ ring to the same open file description is cre‐ ated. An open file description continues to exist until all file descriptors referring to it have been closed. A file descriptor is removed from an epoll set only after all the file descriptors referring to the underlying open file description have been closed (or before if the descriptor is explicitly removed using epoll_ctl(2) EPOLL_CTL_DEL). This means that even after a file descriptor that is part of an epoll set has been closed, events may be reported for that file descriptor if other file descrip‐ tors referring to the same underlying file description remain open.

所以你有一个 fd 42 的套接字。它得到 closed,随后从 epoll 对象中删除。但是内核不会通过 epoll_wait 通知libev 关于这个。现在 epoll_modify 再次调用 fd = 42epoll_modify 不知道这个文件描述符 42 是否与 epoll 对象中已经存在的相同,或者是否重复使用了文件描述符编号 42 的其他文件描述。

有人还可以争辩说评论只是咆哮,libev API 的设计在这里有问题。