Last active
August 29, 2015 14:24
-
-
Save andrewjjenkins/ab0db17a6233a1ce7c15 to your computer and use it in GitHub Desktop.
EOF is level triggered for read and for kevent
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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