Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

If a file is readable before epoll_ctl is called in edge-triggered mode, will a subsequent epoll_wait return immediately?

Tags:

linux

epoll

Does epoll guarantee that the first (or ongoing) call to epoll_wait after a file is registered with epoll_ctl for EPOLLIN and EPOLLET returns immediately in the case that the file was already readable prior to the epoll_ctl call? From my experiments with test programs, it appears that the answer is yes. Here are a couple examples to clarify my question:

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

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

Now consider this scenario:

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

Now does the call in step 3 return immediately? In my experience it does. Is this guaranteed?

Now consider a second scenario, extending the first:

  1. thread1: writes data to fd
  2. thread2: epoll_ctl (efd, EPOLL_CTL_ADD, fd, &event);
  3. thread2: epoll_wait (efd, events, MAXEVENTS, -1);
  4. thread2: epoll_ctl (efd, EPOLL_CTL_MOD, fd, &event);
  5. thread2: epoll_wait (efd, events, MAXEVENTS, -1);

Does the call in step 5 return immediately? In my experience it does. Is it guaranteed?

The epoll man pages are not entirely clear on this issue. In particular, the man pages suggest that you should always read from a file until EAGAIN is returned when using edge-triggered mode. But it seems like those comments are assuming that you are not re-registering the file whenever you want to wait on the file.

what is the purpose of epoll's edge triggered option? is a related discussion. The first two comments to the first answer seem to confirm that the behavior that I see is expected.

https://gist.github.com/3900742 is a C test program that illustrates that epoll with a pipe seems to behave as I've described it.

like image 282
Andreas Avatar asked Oct 16 '12 17:10

Andreas


1 Answers

As epoll is Linux specific there is no real specification, so it's pretty much up to what is actually implemented (the man pages try to describe that in some more user-friendly way, but don't provide all the details for edge-cases).

Looking at ep_insert and ep_modify both check the current event bits (irrespective 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 that explains the behaviour you are seeing and it seems to have been done deliberately. But as there is no specification, there is no cast-iron guarantee that the behaviour won't change in the future.

like image 174
cmeerw Avatar answered Sep 24 '22 00:09

cmeerw