From b2dbf8fd04cb3755ef1592d3b65b3b4d61c00527 Mon Sep 17 00:00:00 2001 From: logwang Date: Thu, 21 Dec 2017 22:45:10 +0800 Subject: [PATCH] Example: fix listen queue overflow. According to the FreeBSD Manual Page: - When kevent() returns and if `flags` is EVFILT_READ, sockets which have previously been passed to listen() return when there is an incoming connection pending. `data` contains the size of the listen backlog. So if an EVFILT_READ event reaches and it is the listen socket, we must accept `event->data` times. And for `ff_epoll` interface, we should continue to accept until it fails. In the previous version, we only accept once when event reaches, it will cause listen queue overflow. --- example/main.c | 45 ++++++++++++++++++-------------------------- example/main_epoll.c | 27 +++++++++++++------------- 2 files changed, 32 insertions(+), 40 deletions(-) diff --git a/example/main.c b/example/main.c index 083f3eb2..74580a15 100644 --- a/example/main.c +++ b/example/main.c @@ -66,38 +66,34 @@ int loop(void *arg) /* Handle disconnect */ if (event.flags & EV_EOF) { - /* Simply close socket */ ff_close(clientfd); - - //printf("A client has left the server...,fd:%d\n", clientfd); } else if (clientfd == sockfd) { - int nclientfd = ff_accept(sockfd, NULL, NULL); - if (nclientfd < 0) { - printf("ff_accept failed:%d, %s\n", errno, strerror(errno)); - continue; - } + int available = (int)event.data; + do { + int nclientfd = ff_accept(sockfd, NULL, NULL); + if (nclientfd < 0) { + printf("ff_accept failed:%d, %s\n", errno, + strerror(errno)); + break; + } - /* Add to event list */ - kevSet.data = 0; - kevSet.fflags = 0; - kevSet.filter = EVFILT_READ; - kevSet.flags = EV_ADD; - kevSet.ident = nclientfd; - kevSet.udata = NULL; + /* Add to event list */ + EV_SET(&kevSet, nclientfd, EVFILT_READ, EV_ADD, 0, 0, NULL); - assert(ff_kevent(kq, &kevSet, 1, NULL, 0, NULL) == 0); - - //printf("A new client connected to the server..., fd:%d\n", nclientfd); + if(ff_kevent(kq, &kevSet, 1, NULL, 0, NULL) < 0) { + printf("ff_kevent error:%d, %s\n", errno, + strerror(errno)); + return -1; + } + available--; + } while (available); } else if (event.filter == EVFILT_READ) { char buf[256]; size_t readlen = ff_read(clientfd, buf, sizeof(buf)); - //printf("bytes %zu are available to read...,fd:%d\n", (size_t)event.data, clientfd); - ff_write(clientfd, html, sizeof(html)); - } else { printf("unknown event: %8.8X\n", event.flags); } @@ -133,12 +129,7 @@ int main(int argc, char * argv[]) exit(1); } - kevSet.data = MAX_EVENTS; - kevSet.fflags = 0; - kevSet.filter = EVFILT_READ; - kevSet.flags = EV_ADD; - kevSet.ident = sockfd; - kevSet.udata = NULL; + EV_SET(&kevSet, sockfd, EVFILT_READ, EV_ADD, 0, MAX_EVENTS, NULL); assert((kq = ff_kqueue()) > 0); diff --git a/example/main_epoll.c b/example/main_epoll.c index ed8f4ff8..e597689c 100644 --- a/example/main_epoll.c +++ b/example/main_epoll.c @@ -65,33 +65,34 @@ int loop(void *arg) for (i = 0; i < nevents; ++i) { /* Handle new connect */ if (events[i].data.fd == sockfd) { - int nclientfd = ff_accept(sockfd, NULL, NULL); - if (nclientfd < 0) { - printf("ff_accept failed:%d, %s\n", errno, strerror(errno)); - continue; - } + while (1) { + int nclientfd = ff_accept(sockfd, NULL, NULL); + if (nclientfd < 0) { + break; + } - /* Add to event list */ - ev.data.fd = nclientfd; - ev.events = EPOLLIN; - assert(ff_epoll_ctl(epfd, EPOLL_CTL_ADD, nclientfd, &ev) == 0); - //printf("A new client connected to the server..., fd:%d\n", nclientfd); + /* Add to event list */ + ev.data.fd = nclientfd; + ev.events = EPOLLIN; + if (ff_epoll_ctl(epfd, EPOLL_CTL_ADD, nclientfd, &ev) != 0) { + printf("ff_epoll_ctl failed:%d, %s\n", errno, + strerror(errno)); + break; + } + } } else { if (events[i].events & EPOLLERR ) { /* Simply close socket */ ff_epoll_ctl(epfd, EPOLL_CTL_DEL, events[i].data.fd, NULL); ff_close(events[i].data.fd); - //printf("A client has left the server...,fd:%d\n", events[i].data.fd); } else if (events[i].events & EPOLLIN) { char buf[256]; size_t readlen = ff_read( events[i].data.fd, buf, sizeof(buf)); - //printf("bytes are available to read..., readlen:%d, fd:%d\n", readlen, events[i].data.fd); if(readlen > 0) { ff_write( events[i].data.fd, html, sizeof(html)); } else { ff_epoll_ctl(epfd, EPOLL_CTL_DEL, events[i].data.fd, NULL); ff_close( events[i].data.fd); - //printf("A client has left the server...,fd:%d\n", events[i].data.fd); } } else { printf("unknown event: %8.8X\n", events[i].events);