The Linux Programming Interface

(nextflipdebug5) #1

1364 Chapter 63


as the epfd argument in a call to epoll_ctl(). Similarly, we can retrieve items from
the ready list by specifying either file descriptor as the epfd argument in a call to
epoll_wait().
z The preceding point also applies after a call to fork(). The child inherits a dupli-
cate of the parent’s epoll file descriptor, and this duplicate descriptor refers to
the same epoll data structures.

When we perform an epoll_ctl() EPOLL_CTL_ADD operation, the kernel adds an item to
the epoll interest list that records both the number of the monitored file descriptor
and a reference to the corresponding open file description. For the purpose of
epoll_wait() calls, the kernel monitors the open file description. This means that we
must refine our earlier statement that when a file descriptor is closed, it is automatically
removed from any epoll interest lists of which it is a member. The refinement is this: an
open file description is removed from the epoll interest list once all file descriptors that
refer to it have been closed. This means that if we create duplicate descriptors refer-
ring to an open file—using dup() (or similar) or fork()—then the open file will be
removed only after the original descriptor and all of the duplicates have been closed.
These semantics can lead to some behavior that at first appears surprising.
Suppose that we execute the code shown in Listing 63-6. The epoll_wait() call in this
code will tell us that the file descriptor fd1 is ready (in other words, evlist[0].data.fd
will be equal to fd1), even though fd1 has been closed. This is because there is still
one open file descriptor, fd2, referring to the open file description contained in the
epoll interest list. A similar scenario occurs when two processes hold duplicate
descriptors for the same open file description (typically, as a result of a fork()), and
the process performing the epoll_wait() has closed its file descriptor, but the other
process still holds the duplicate descriptor open.

Listing 63-6: Semantics of epoll with duplicate file descriptors

int epfd, fd1, fd2;
struct epoll_event ev;
struct epoll_event evlist[MAX_EVENTS];

/* Omitted: code to open 'fd1' and create epoll file descriptor 'epfd' ... */

ev.data.fd = fd1
ev.events = EPOLLIN;
if (epoll_ctl(epfd, EPOLL_CTL_ADD, fd1, ev) == -1)
errExit("epoll_ctl");

/* Suppose that 'fd1' now happens to become ready for input */

fd2 = dup(fd1);
close(fd1);
ready = epoll_wait(epfd, evlist, MAX_EVENTS, -1);
if (ready == -1)
errExit("epoll_wait");
Free download pdf