Commit b399e87e authored by Jeremy Soller's avatar Jeremy Soller

Add epoll test

parent dd9328bd
sys_includes = []
sys_includes = ["signal.h"]
include_guard = "_SYS_EPOLL_H"
language = "C"
style = "Tag"
......
......@@ -61,6 +61,7 @@ EXPECT_BINS=\
string/strtok \
string/strtok_r \
strings \
sys_epoll/epoll \
time/asctime \
time/gmtime \
time/localtime \
......
This diff is collapsed.
#include <fcntl.h>
#include <stdio.h>
#include <sys/epoll.h>
#include <sys/wait.h>
#include <unistd.h>
int reader(int fd) {
// Create an epoll file
int epollfd = epoll_create1(EPOLL_CLOEXEC);
if (epollfd < 0) {
perror("epoll_create1");
return 1;
}
// Register for events from the reader file
struct epoll_event ev;
ev.events = EPOLLIN;
ev.data.fd = fd;
if (epoll_ctl(epollfd, EPOLL_CTL_ADD, fd, &ev) < 0) {
perror("epoll_ctl");
return 1;
}
// Process exactly 1024 events
struct epoll_event events[8];
for (int i = 0; i < 1024; i++) {
// Wait for the next event
int nfds = epoll_wait(epollfd, events, sizeof(events)/sizeof(struct epoll_event), -1);
if (nfds < 0) {
perror("epoll_wait");
return 1;
}
// For each event received
for (int n = 0; n < nfds; n++) {
// If the event is the reader file
if (events[n].data.fd == fd) {
// Read the current event count
int writer_i;
int count = read(fd, &writer_i, sizeof(writer_i));
if (count < 0) {
perror("read");
return 1;
} else if (count < sizeof(writer_i)) {
fprintf(stderr, "read %d instead of %d\n", count, sizeof(writer_i));
return 1;
}
// Make sure the writer's event count matches our own
if (i != writer_i) {
fprintf(stderr, "received event count %d instead of %d\n", writer_i, i);
return 1;
}
printf("%d == %d\n", i, writer_i);
} else {
// Otherwise, return an error
fprintf(stderr, "unknown fd %d\n", events[n].data.fd);
return 1;
}
}
}
return 0;
}
int writer(int fd) {
// Create an epoll file
int epollfd = epoll_create1(EPOLL_CLOEXEC);
if (epollfd < 0) {
perror("epoll_create1");
return 1;
}
// Register for events from the writer file
struct epoll_event ev;
ev.events = EPOLLOUT;
ev.data.fd = fd;
if (epoll_ctl(epollfd, EPOLL_CTL_ADD, fd, &ev) < 0) {
perror("epoll_ctl");
return 1;
}
// Process exactly 1024 events
struct epoll_event events[8];
for (int i = 0; i < 1024; i++) {
// Wait for the next event
int nfds = epoll_wait(epollfd, events, sizeof(events)/sizeof(struct epoll_event), -1);
if (nfds < 0) {
perror("epoll_wait");
return 1;
}
// For each event received
for (int n = 0; n < nfds; n++) {
// If the event is the writer file
if (events[n].data.fd == fd) {
// Write the current event count
int count = write(fd, &i, sizeof(i));
if (count < 0) {
perror("write");
return 1;
} else if (count < sizeof(i)) {
fprintf(stderr, "wrote %d instead of %d\n", count, sizeof(i));
return 1;
}
} else {
// Otherwise, return an error
fprintf(stderr, "unknown fd %d\n", events[n].data.fd);
return 1;
}
}
}
return 0;
}
int main(int argc, char **argv) {
// Create a non-blocking pipe to use for epoll testing
int pipefd[2];
if (pipe2(pipefd, O_CLOEXEC | O_NONBLOCK) < 0) {
perror("pipe2");
return 1;
}
pid_t pid = fork();
if (pid < 0) {
perror("fork");
return 1;
} else if (pid == 0) {
// Child process will read events
close(pipefd[1]);
return reader(pipefd[0]);
} else {
// Parent process will write events
close(pipefd[0]);
int ret = writer(pipefd[1]);
// Wait for child process
int status = 0;
if (waitpid(pid, &status, 0) != pid) {
perror("waitpid");
return 1;
}
// If writer failed, return exit status
if (ret != 0) {
return ret;
}
// If child exited with exit status
if (WIFEXITED(status)) {
// Return the child's exit status
return WEXITSTATUS(status);
} else {
// Otherwise, return 1
return 1;
}
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment