Question

I am having trouble understanding this from the epoll documentation: Say I have pipe(fd) so we have fd[0] for reading and fd[1] for writing. We write some stuff to fd[1] and then close it:

write(fd[1], "abc", 3);
write(fd[1], "def", 3);
close(fd[1]);

Potentially simultaneously, we create an epoll instance, tell it to wait until it can read from fd[0], and read 3 bytes once it does.

int epoll_fd = epoll_create(10);
struct epoll_event ev;
ev.events = EPOLLIN;
ev.data.fd = fd[0];
epoll_ctl(epoll_fd, EPOLL_CTL_ADD, fd[0], &ev);

struct epoll_event event;
epoll_wait(epoll_fd, &event, 1, -1);
char buffer[100];
read(fd[0], buffer, 3);

Now we call epoll_wait again. Even though pipe is closed, the kernel should still have 3 bytes buffered for us available to be read from fd[0], yes? So I'd expect the following to work (ie, not block):

epoll_wait(epoll_fd, &event, 1, -1);
read(fd[0], buffer, 3);  // buffer should start with "def" now

Now there's nothing left in the pipe and the write end is closed. What should happen if I epoll_wait a third time?

epoll_wait(epoll_fd, &event, 1, -1);  // will this block indefinitely?
read(fd[0], buffer, 3);

I have two different pieces of code both seeming to indicate different answers here, so I'd like to know what should be happening to better decipher what's going on.

Was it helpful?

Solution

the write end of a pipe being closed should be signaled with read() returning 0.

Assuming:

  • You're not using epoll edge trigger
  • You have checked all calls for errors.
  • The write end really is closed (i.e. there's no leaked descriptor from e.g. a dup() call or fork())

then your last epoll_wait should not block, and the following read() should return 0.

(And remember to check that read() returns the amount of bytes you assume it returns)

OTHER TIPS

Regarding this line of your post:

epoll_wait(epoll_fd, &event, 1, -1);  // will this block indefinitely?  

the maxevents argument is set to 1, so you should see up to only one event regardless, but that has litte to do with your question, really.
the timeout argument is set to -1, this will cause epoll_wait() to block indefinitely

if you do not want it to block, or pass some finite amount of time, then pass 0 for timeout, this will cause epoll_wait() to return immediately, even if there are no events.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top