Is it possible to use epoll
in one-shot level-triggered mode?
I couldn't find any information on it when I searched; it seems everyone uses edge-triggered mode.

- 205,094
- 128
- 528
- 886
2 Answers
When the EPOLLONESHOT
flag is selected and you have pulled an event for a socket, then the socket won't get removed from epoll as many think but its events get disabled. You can enable them again using epoll_ctl
/ EPOLL_CTL_MOD
.
An example case when the EPOLLONESHOT
behavior comes handy is when you've read the available data from a socket into a buffer. That buffer would be emptied independently, but until it isn't empty, you have to disable the socket events, even if the socket has additional data. Then after the buffer got used and emptied, you can re-enable the socket.
The difference between the edge- and level-triggered "one shot" behaviors come only when you re-enable the socket. An example:
- The socket receives 7K data (for now it's stored in a kernel buffer)
- You wait for an input event, then the socket events get disabled due to the EPOLLONESHOT.
- You read 4K into an application level buffer.
- Later the application buffer gets used and emptied. You re-enable the socket with
epoll_ctl
/EPOLL_CTL_MOD
.
Level-triggered EPOLLONESHOT:
- Since 3K data is still present in the kernel buffers, the event is triggered again.
Edge-triggered EPOLLONESHOT:
- It won't trigger an event again for the available data. You must test it by reading, and waiting for
EAGAIN
/EWOULDBLOCK
.

- 1,135
- 12
- 23
-
1According to my experiment. Edge-triggered EPOLLONESHOT doesn't work like your description. It works just the same as level-triggered EPOLLONESHOT. – libo Jun 16 '21 at 02:20
-
@libo HA! Glad to hear it. I’m using lib dispatch which apparently uses one shot, but not `POLLET`, and I’ve observed that I’m not always called back when there are more data to read after I read something. The only working solution I got is to use an async fd and read until `EAGAIN`, and then I’m always called. It’s weird. Don’t know if libdispatch bug, epoll bug, or just something I did not understand… – Frizlab Aug 20 '21 at 10:58
If you want epoll to stop listening on a socket the you should use EPOLLONESHOT. If you do use EPOLLONESHOT then you will have to add the socket back to epoll after epoll signals on that socket. Thus EPOLLONESHOT is not EPOLLET. You can use EPOLLONESHOT without EPOLLET, but it might not be efficient. If you use both the flags, then you will have to make use of non blocking sockets and add a socket to epoll only once recv and send return with an EAGAIN error. Please refer to man page for details.

- 96
- 2
-
1As pointed by Crouching Kitten (and as I confirmed while implementing) you do not have to add the socket but just rearm the events. – Sunny Aug 29 '19 at 13:17