If the file is read before epoll_ctl is called in edge mode, will epoll_wait return immediately?

Does epoll guarantee that the first (or current) call to epoll_wait after registering the epoll_ctl file for EPOLLIN and EPOLLET will return immediately if the file was already readable before calling epoll_ctl? From my experiments with test programs, the answer seems to be yes. Here are some examples to clarify my question:

Suppose we initialized the epoll efd file and the fd file and the following event definition:

 event.data.fd = fd; event.events = EPOLLIN | EPOLLET; 

Now consider this scenario:

  • thread1: writes data to fd
  • thread2: epoll_ctl (efd, EPOLL_CTL_ADD, fd, &event);
  • thread2: epoll_wait (efd, events, MAXEVENTS, -1);

Now the call in step 3 returns immediately? In my experience, this is so. Is it guaranteed?

Now consider the second scenario extending the first:

  • thread1: writes data to fd
  • thread2: epoll_ctl (efd, EPOLL_CTL_ADD, fd, &event);
  • thread2: epoll_wait (efd, events, MAXEVENTS, -1);
  • thread2: epoll_ctl (efd, EPOLL_CTL_MOD, fd, &event);
  • thread2: epoll_wait (efd, events, MAXEVENTS, -1);

Does the call return in step 5 immediately? In my experience, this is so. Is it guaranteed?

The pages with epoll man are not entirely clear on this issue. In particular, the manual pages suggest that you should always read from a file until EAGAIN is returned when using edge-triggered mode. But it seems that these comments suggest that you do not re-register the file when you want to wait for the file.

What is the purpose of the front-generated variant of epoll? - this is a related discussion. The first two comments on the first answer seem to confirm that the behavior I am seeing is expected.

https://gist.github.com/3900742 is a C test program that shows that the pipe epoll seems to behave the way I described.

+4
source share
1 answer

Since epoll is specific to Linux, there is no real specification, so it largely depends on what is actually implemented (man pages try to describe it in a more user-friendly way, but do not provide all the details for edge cases).

Looking at ep_insert and ep_modify , check the current event bits (regardless of EPOLLET ):

 /* * Get current event bits. We can safely use the file* here because * its usage count has been increased by the caller of this function. */ revents = epi->ffd.file->f_op->poll(epi->ffd.file, &pt); 

So this explains the behavior you see, and it seems like it was done on purpose. But since there is no specification, there is no cast-iron guarantee that behavior will not change in the future.

+4
source

Source: https://habr.com/ru/post/1440102/


All Articles