man epoll:
The suggested way to use epoll as an edge-triggered (EPOLLET) interface is as follows:
i with nonblocking file descriptors; and
ii by waiting for an event only after read(2) or write(2) return EAGAIN.
Imagine we have two fds: the first is passive, data available only sometimes, the second is active, data only sometimes not available.
epoll_wait returned that we can read both. We read { the first, than the second } in a loop (without calls to epoll_wait because of it may suddenly block while the data is still available).
Now the first file descriptor returned EAGAIN on read.
What to do?
- If we go on reading the second fd in a loop (without calls to epoll_wait), we can miss that the data have become available on the first fd. It will just read and read and read without EAGAIN.
- If we will "consult" with epoll_wait before each read from the second fd, epoll_wait may SUDDENLY block because of nothing changed from the previous call (data still not available on the first FD and still available on the second FD).
How to continue processing of the second FD, but without forgetting about the first FD?
Update: Found one more thing: man epoll_wait:
while specifying timeout equal to zero makes epoll_wait() to return immediately even if no events are available
With this I can enumerate events for FDs even if there are no events.