A few epoll jots
Just a few things I wrote down while getting the hang on Linux’ epoll working with a named pipe. There’s also a little test program at Github.
- Be sure to read this and this.
- An event list for a file descriptor can be added only once with epoll_ctl(…, EPOLL_CTL_ADD, …). Calling epoll_ctl for adding an event entry for a file descriptor which is already listed results with an EEXIST error (the manual says so, and hey, it also happens).
- The @events member passed to epoll_ctl() is an OR of all events to watch. The @events member in the array of events returned by epoll_wait() are the events that are in effect.
- It’s fine to register events that are unrelated (i.e. will never happen), not that there’s any reason to do so deliberately.
- If several events are triggered for the same file descriptor, they are ORed in one array entry by epoll_wait().
- Without the EPOLLET flag (edge-triggered), the same event keeps appearing endlessly until cleared by some I/O action.
- In particular, EPOLLHUP is returned continuously on a FIFO (named pipe) opened for read with the other side unopened.
- Same for EPOLLERR with a FIFO opened for write.
- In edge-triggered mode (with EPOLLET) an event is generated each time new data is fed or drained on the other side, even if the previous data hasn’t been cleared. In this sense, it isn’t really edge-triggered. Probably the calls to wake_up() (in different variants) in the driver causes this.
- As expected, if a FIFO is opened for read with O_NONBLOCK, there is no event whatsoever when the other side is opened — only when data arrives.
- Important: If the counterpart side is closed and then reopened while there is no epoll_wait() blocking, this will go unnoticed. The solution is probably to have a tight loop only picking up events, and let some other thread take it from there.