Skip to content

Instantly share code, notes, and snippets.

@andrewjjenkins
Last active August 29, 2015 14:24
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save andrewjjenkins/ab0db17a6233a1ce7c15 to your computer and use it in GitHub Desktop.
Save andrewjjenkins/ab0db17a6233a1ce7c15 to your computer and use it in GitHub Desktop.
EOF is level triggered for read and for kevent
#include <stdio.h>
#include <strings.h>
#include <assert.h>
#include <unistd.h>
#include <errno.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/event.h>
#include <sys/time.h>
#include <sys/socket.h>
#include <netinet/in.h>
void setNonBlock(int fd) {
int flags = fcntl(fd, F_GETFL, 0);
assert(flags >= 0);
assert(fcntl(fd, F_SETFL, flags | O_NONBLOCK) == 0);
}
int main (int argc, char **argv) {
int fd[2], kq;
char readBuf[100];
// Make a socket pair, set nonblocking.
assert(0 == socketpair(PF_LOCAL, SOCK_STREAM, 0, fd));
setNonBlock(fd[0]);
setNonBlock(fd[1]);
// Listen for read events on fd[1]
kq = kqueue();
struct kevent kqReads[1];
bzero(kqReads, sizeof(struct kevent) * 1);
kqReads[0].ident = fd[1];
kqReads[0].filter = EVFILT_READ;
kqReads[0].flags = EV_ADD;
struct kevent events[1];
const struct timespec kev_time = { 0, 0 };
assert(0 == kevent(kq, kqReads, 1, events, 1, &kev_time));
// Try reading from both fds, should get EWOULDBLOCK
assert(-1 == read(fd[0], readBuf, 100));
assert(errno == EWOULDBLOCK);
assert(-1 == read(fd[1], readBuf, 100));
assert(errno == EWOULDBLOCK);
// SHUT_RDWR fd[0]. fd[1] should start getting EOF, and EVFILT_READ
assert(0 == shutdown(fd[0], SHUT_RDWR));
assert(1 == kevent(kq, NULL, 0, events, 1, &kev_time));
assert(events[0].ident == fd[1]);
assert(events[0].filter == EVFILT_READ);
// Continue polling. EOF is "level-triggered":
// - Keep reading from fd[1], keep getting EOF.
// - Keep checking for kevents, keep getting EVFILT_READ.
assert(0 == read(fd[1], readBuf, 100));
assert(1 == kevent(kq, NULL, 0, events, 1, &kev_time));
assert(events[0].ident == fd[1]);
assert(events[0].filter == EVFILT_READ);
assert(0 == read(fd[1], readBuf, 100));
assert(1 == kevent(kq, NULL, 0, events, 1, &kev_time));
assert(events[0].ident == fd[1]);
assert(events[0].filter == EVFILT_READ);
assert(0 == read(fd[1], readBuf, 100));
assert(1 == kevent(kq, NULL, 0, events, 1, &kev_time));
assert(events[0].ident == fd[1]);
assert(events[0].filter == EVFILT_READ);
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment