summaryrefslogtreecommitdiffhomepage
path: root/src/event/ngx_event_accept.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/event/ngx_event_accept.c')
-rw-r--r--src/event/ngx_event_accept.c58
1 files changed, 58 insertions, 0 deletions
diff --git a/src/event/ngx_event_accept.c b/src/event/ngx_event_accept.c
index b05666c76..27038799d 100644
--- a/src/event/ngx_event_accept.c
+++ b/src/event/ngx_event_accept.c
@@ -11,6 +11,9 @@
static ngx_int_t ngx_disable_accept_events(ngx_cycle_t *cycle, ngx_uint_t all);
+#if (NGX_HAVE_EPOLLEXCLUSIVE)
+static void ngx_reorder_accept_events(ngx_listening_t *ls);
+#endif
static void ngx_close_accepted_connection(ngx_connection_t *c);
@@ -314,6 +317,10 @@ ngx_event_accept(ngx_event_t *ev)
}
} while (ev->available);
+
+#if (NGX_HAVE_EPOLLEXCLUSIVE)
+ ngx_reorder_accept_events(ls);
+#endif
}
@@ -420,6 +427,57 @@ ngx_disable_accept_events(ngx_cycle_t *cycle, ngx_uint_t all)
}
+#if (NGX_HAVE_EPOLLEXCLUSIVE)
+
+static void
+ngx_reorder_accept_events(ngx_listening_t *ls)
+{
+ ngx_connection_t *c;
+
+ /*
+ * Linux with EPOLLEXCLUSIVE usually notifies only the process which
+ * was first to add the listening socket to the epoll instance. As
+ * a result most of the connections are handled by the first worker
+ * process. To fix this, we re-add the socket periodically, so other
+ * workers will get a chance to accept connections.
+ */
+
+ if (!ngx_use_exclusive_accept) {
+ return;
+ }
+
+#if (NGX_HAVE_REUSEPORT)
+
+ if (ls->reuseport) {
+ return;
+ }
+
+#endif
+
+ c = ls->connection;
+
+ if (c->requests++ % 16 != 0
+ && ngx_accept_disabled <= 0)
+ {
+ return;
+ }
+
+ if (ngx_del_event(c->read, NGX_READ_EVENT, NGX_DISABLE_EVENT)
+ == NGX_ERROR)
+ {
+ return;
+ }
+
+ if (ngx_add_event(c->read, NGX_READ_EVENT, NGX_EXCLUSIVE_EVENT)
+ == NGX_ERROR)
+ {
+ return;
+ }
+}
+
+#endif
+
+
static void
ngx_close_accepted_connection(ngx_connection_t *c)
{