[nginx] Events: support for EPOLLRDHUP (ticket #320).

Valentin Bartenev vbart at nginx.com
Mon Sep 16 14:34:50 UTC 2013


details:   http://hg.nginx.org/nginx/rev/36b58ddb566d
branches:  
changeset: 5372:36b58ddb566d
user:      Valentin Bartenev <vbart at nginx.com>
date:      Fri Jul 12 14:51:07 2013 +0400
description:
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.

diffstat:

 auto/modules                         |   1 +
 auto/os/linux                        |  16 ++++++++++++++++
 src/event/modules/ngx_epoll_module.c |  18 +++++++++++++-----
 src/event/ngx_event.h                |   9 +++++++--
 4 files changed, 37 insertions(+), 7 deletions(-)

diffs (130 lines):

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 @@ fi
 
 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 @@ if [ $ngx_found = yes ]; then
     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 <sys/epoll.h>"
+    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 @@ ngx_epoll_add_event(ngx_event_t *ev, ngx
     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 @@ ngx_epoll_del_event(ngx_event_t *ev, ngx
 
     } else {
         e = c->read;
-        prev = EPOLLIN;
+        prev = EPOLLIN|EPOLLRDHUP;
     }
 
     if (e->active) {
@@ -501,7 +503,7 @@ ngx_epoll_add_connection(ngx_connection_
 {
     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 @@ ngx_epoll_process_events(ngx_cycle_t *cy
 
         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 @@ struct ngx_event_s {
 
     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 @@ extern ngx_event_actions_t   ngx_event_a
 #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 @@ extern ngx_event_actions_t   ngx_event_a
 
 #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



More information about the nginx-devel mailing list