Are epoll events monitored when not epoll_waiting
I am new to event based programming. I am experimenting with epoll
edge mode , which apparently only signals files that have become read / write ready (as opposed to level-mode, which signals all files ready, whether they were already done or just done) ...
What I don't understand is there: in edge-mode, am I informed about readiness events that occur while I'm not epoll_wait
ing? How about events in one-shot files that haven't been reloaded yet?
To illustrate why I am asking this, consider the following scenario:
- 10 non-blocking sockets connected
- configure to
epoll_ctl
react when sockets are ready to read, in edge + onehot mode :EPOLLET | EPOLLONESHOT | EPOLLIN
-
epoll_wait
for something (reports max 10 events) - linux wakes up my process and says sockets # 1 and # 2 are ready
- me
read
and process data socket # 1 (beforeE_AGAIN
) - me
read
and process data socket # 2 (beforeE_AGAIN
) - While I do this , socket S is receiving data
- I handled all events, so I reloaded the runnable files using
epoll_ctl
inEPOLL_CTL_MOD
mode due to onehot - my loop goes back
epoll_wait
to next batch of events
Ok, so will the latter epoll_wait
be notified when socket S is ready? Event if S is # 1 (i.e. it is not reloaded)?
source to share
I am experimenting with epoll edge-mode, which apparently only signals files ready for read / write (as opposed to level mode which signals all files ready, no matter if they were ready or just ready)
Let's take a look at the system first, you need an accurate mental model of how the system works. Your view is epoll(7)
not very accurate.
The difference between edge triggering and level triggering is the definition of what exactly the event does. The first generates one event for each action that has been subscribed to a file descriptor; once you use this event, it will disappear, even if you haven't destroyed all the data that generated such an event. OTOH, the latter keeps on unrolling the same event over and over until you destroy all the data that generated the event.
Here's an example that puts these concepts into action, clearly stolen from man 7 epoll
:
A file descriptor representing the read-side of the pipe (rfd) is registered with the epoll instance.
The pipe writer writes 2KB of data on the write side of the pipe.
A call to epoll_wait (2) is made, which will return rfd as a file descriptor for the finished file.
The channel reader reads 1 kbyte of data from the rfd.
A call to epoll_wait (2) is made.
If the rfd file descriptor was added to the epoll interface using the EPOLLET flag (with an edge), the call to epoll_wait (2) made in step 5 is likely to hang, despite the data still present in the file's input buffer; meanwhile, the remote peer can wait based on the data it has already sent. The reason for this is that this edge mode provides events only when changes occur to a controlled file descriptor. So, in step 5, the caller might be waiting for some data that is already present in the input buffer. In the above example, an event on rfd will be generated because the write is performed at 2 and the event is consumed at 3. Since the read operation performed at 4 does not consume all of the buffer data, the call to epoll_wait (2) performed in step 5,can block indefinitely.
In short, the main difference is in the definition of an "event": edge-triggered treats events as a whole, which you consume once; level-triggered defines the consumption of an event as equivalent to the consumption of all data belonging to that event.
Now with that in mind, let's look at your specific questions.
in edge-mode, I am informed about ready events that happen when I am not epoll_waiting
Yes you. Inside the core of the queue, interesting events are awaiting that have occurred in each file descriptor. They are returned on the next call epoll_wait(2)
, so you can be sure not to lose events. Well, maybe not quite on the next call, if other events are awaiting and the event buffer passed to epoll_wait(2)
cannot accommodate them, but the point is that these events will be reported eventually.
How about events in one-shot files that haven't been reloaded yet?
Again, you never lose track of events. If the file descriptor has not been reloaded yet, some interesting event should occur, it is simply queued in memory until the file descriptor is reloaded. After reloading it, any pending events, including those that happened before the handle was reloaded, will be reported on the next call epoll_wait(2)
(again, maybe not quite the next one, but they will be reported). In other words, it EPOLLONESHOT
doesn't disable event monitoring, it temporarily disables event notification.
Ok, so will the last epoll_wait always be reported when the Socket is ready? Event if S is # 1 (i.e. it is not reloaded)?
Given what I said above, it should be pretty clear by now: yes it will. You will not lose a single event. epoll offers strong guarantees, it's amazing. It is also thread safe and you can wait for the same epoll fd on different threads and update your event subscription at the same time. epoll is very powerful and well worth taking the time to learn!
source to share