Skip to content

Instantly share code, notes, and snippets.

@baixiangcpp
Created August 1, 2018 15:29
Show Gist options
  • Save baixiangcpp/874897d09a4eb4f8b3fbdc93b1e2869c to your computer and use it in GitHub Desktop.
Save baixiangcpp/874897d09a4eb4f8b3fbdc93b1e2869c to your computer and use it in GitHub Desktop.
file-descriptor starvation when using epoll edge-triggered notification
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/epoll.h>
#include <sys/socket.h>
#include <fcntl.h>
#include <strings.h>
#include <errno.h>
#include <netinet/in.h>
#define MAX_EVENTS 10
#define BUF_SIZE 100
void onError(const char *why)
{
perror(why);
exit(EXIT_FAILURE);
}
void handle_conn(int epollfd, int fd)
{
struct sockaddr_in addr = {0};
int socket = accept(fd, NULL, NULL);
if (socket == -1)
onError("accpet");
struct epoll_event epollev;
epollev.events = EPOLLIN | EPOLLET;
epollev.data.fd = socket;
if (epoll_ctl(epollfd, EPOLL_CTL_ADD, socket, &epollev) == -1)
onError("epoll_ctl add fd");
printf("%d added\n", socket);
}
int initServSocket(int port)
{
struct sockaddr_in sin;
int servsock = socket(AF_INET, SOCK_STREAM | SOCK_NONBLOCK, 0);
if (servsock == -1)
onError("socket()");
bzero(&sin, sizeof(sin));
sin.sin_family = AF_INET;
sin.sin_addr.s_addr = INADDR_ANY;
sin.sin_port = htons(port);
if (bind(servsock, (struct sockaddr *)&sin, sizeof(sin)) == -1)
onError("bind()");
listen(servsock, SOMAXCONN);
return servsock;
}
void handle_read(int epollfd,int fd)
{
while (1)
{
char buf[BUF_SIZE];
bzero(buf, BUF_SIZE);
int ret = read(fd, buf, BUF_SIZE);
if (ret == -1)
{
if (errno == EAGAIN)
break;
}
if (ret <= 0)
{
epoll_ctl(epollfd, EPOLL_CTL_DEL, fd, NULL);
close(fd);
break;
}
printf("%s \n", buf);
}
}
int main()
{
struct epoll_event ev, events[MAX_EVENTS];
int nfds, epollfd, n, ret;
int servsock = initServSocket(9999);
epollfd = epoll_create1(0);
if (epollfd == -1)
onError("epoll_create1");
ev.events = EPOLLIN | EPOLLET;
ev.data.fd = servsock;
if (epoll_ctl(epollfd, EPOLL_CTL_ADD, servsock, &ev) == -1)
onError("epoll_ctl");
for (;;)
{
int n = 0;
nfds = epoll_wait(epollfd, events, MAX_EVENTS, -1);
if (nfds == -1)
{
perror("epoll_wait");
exit(EXIT_FAILURE);
}
for (n = 0; n < nfds; ++n)
{
if (events[n].data.fd == servsock)
{
handle_conn(epollfd, servsock);
}
else
{
handle_read(epollfd,events[n].data.fd);
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment