# HG changeset patch # User Valentin Bartenev # Date 1373626267 -14400 # Node ID 36b58ddb566d87d0a8b7dd81d633d5e4b0f54bca # Parent b95e70ae6bcdbae99a967df01e1011839f19ee0e Events: support for EPOLLRDHUP (ticket #320). Since Linux 2.6.17, epoll is able to report about peer half-closed connection using special EPOLLRDHUP flag on a read event. diff -r b95e70ae6bcd -r 36b58ddb566d auto/modules --- a/auto/modules Thu Sep 05 16:53:02 2013 +0400 +++ b/auto/modules Fri Jul 12 14:51:07 2013 +0400 @@ -42,6 +42,7 @@ if [ $NGX_TEST_BUILD_EPOLL = YES ]; then have=NGX_HAVE_EPOLL . auto/have + have=NGX_HAVE_EPOLLRDHUP . auto/have have=NGX_HAVE_EVENTFD . auto/have have=NGX_TEST_BUILD_EPOLL . auto/have EVENT_MODULES="$EVENT_MODULES $EPOLL_MODULE" diff -r b95e70ae6bcd -r 36b58ddb566d auto/os/linux --- a/auto/os/linux Thu Sep 05 16:53:02 2013 +0400 +++ b/auto/os/linux Fri Jul 12 14:51:07 2013 +0400 @@ -65,6 +65,22 @@ CORE_SRCS="$CORE_SRCS $EPOLL_SRCS" EVENT_MODULES="$EVENT_MODULES $EPOLL_MODULE" EVENT_FOUND=YES + + + # EPOLLRDHUP appeared in Linux 2.6.17, glibc 2.8 + + ngx_feature="EPOLLRDHUP" + ngx_feature_name="NGX_HAVE_EPOLLRDHUP" + ngx_feature_run=no + ngx_feature_incs="#include " + ngx_feature_path= + ngx_feature_libs= + ngx_feature_test="int efd = 0, fd = 0; + struct epoll_event ee; + ee.events = EPOLLIN|EPOLLRDHUP|EPOLLET; + ee.data.ptr = NULL; + epoll_ctl(efd, EPOLL_CTL_ADD, fd, &ee)" + . auto/feature fi diff -r b95e70ae6bcd -r 36b58ddb566d src/event/modules/ngx_epoll_module.c --- a/src/event/modules/ngx_epoll_module.c Thu Sep 05 16:53:02 2013 +0400 +++ b/src/event/modules/ngx_epoll_module.c Fri Jul 12 14:51:07 2013 +0400 @@ -25,6 +25,8 @@ #define EPOLLERR 0x008 #define EPOLLHUP 0x010 +#define EPOLLRDHUP 0x2000 + #define EPOLLET 0x80000000 #define EPOLLONESHOT 0x40000000 @@ -396,13 +398,13 @@ if (event == NGX_READ_EVENT) { e = c->write; prev = EPOLLOUT; -#if (NGX_READ_EVENT != EPOLLIN) - events = EPOLLIN; +#if (NGX_READ_EVENT != EPOLLIN|EPOLLRDHUP) + events = EPOLLIN|EPOLLRDHUP; #endif } else { e = c->read; - prev = EPOLLIN; + prev = EPOLLIN|EPOLLRDHUP; #if (NGX_WRITE_EVENT != EPOLLOUT) events = EPOLLOUT; #endif @@ -466,7 +468,7 @@ } else { e = c->read; - prev = EPOLLIN; + prev = EPOLLIN|EPOLLRDHUP; } if (e->active) { @@ -501,7 +503,7 @@ { struct epoll_event ee; - ee.events = EPOLLIN|EPOLLOUT|EPOLLET; + ee.events = EPOLLIN|EPOLLOUT|EPOLLET|EPOLLRDHUP; ee.data.ptr = (void *) ((uintptr_t) c | c->read->instance); ngx_log_debug2(NGX_LOG_DEBUG_EVENT, c->log, 0, @@ -666,6 +668,12 @@ if ((revents & EPOLLIN) && rev->active) { +#if (NGX_HAVE_EPOLLRDHUP) + if (revents & EPOLLRDHUP) { + rev->pending_eof = 1; + } +#endif + if ((flags & NGX_POST_THREAD_EVENTS) && !rev->accept) { rev->posted_ready = 1; diff -r b95e70ae6bcd -r 36b58ddb566d src/event/ngx_event.h --- a/src/event/ngx_event.h Thu Sep 05 16:53:02 2013 +0400 +++ b/src/event/ngx_event.h Fri Jul 12 14:51:07 2013 +0400 @@ -71,7 +71,7 @@ unsigned deferred_accept:1; - /* the pending eof reported by kqueue or in aio chain operation */ + /* the pending eof reported by kqueue, epoll or in aio chain operation */ unsigned pending_eof:1; #if !(NGX_THREADS) @@ -349,6 +349,11 @@ #define NGX_VNODE_EVENT 0 +#if (NGX_HAVE_EPOLL) && !(NGX_HAVE_EPOLLRDHUP) +#define EPOLLRDHUP 0 +#endif + + #if (NGX_HAVE_KQUEUE) #define NGX_READ_EVENT EVFILT_READ @@ -392,7 +397,7 @@ #elif (NGX_HAVE_EPOLL) -#define NGX_READ_EVENT EPOLLIN +#define NGX_READ_EVENT (EPOLLIN|EPOLLRDHUP) #define NGX_WRITE_EVENT EPOLLOUT #define NGX_LEVEL_EVENT 0