[PATCH] Events: improve ngx_notify() interface

Piotr Sikora piotrsikora at google.com
Thu Aug 18 00:29:40 UTC 2016


# HG changeset patch
# User Piotr Sikora <piotrsikora at google.com>
# Date 1471265536 25200
#      Mon Aug 15 05:52:16 2016 -0700
# Node ID e4241e448bc94e6b598a2178d7378aef63741f3c
# Parent  c131f20c9562387f94a268440594c288725d3ba8
Events: improve ngx_notify() interface.

Previous implementation had a race condition in which only the last
of the notified handlers was called, i.e.:

    ngx_notify(ngx_ping_handler);
    ngx_notify(ngx_pong_handler);

resulted in only ngx_pong_handler() being called.

This wasn't an issue in standalone NGINX (because there is only one
consumer of this interface), but it led to lost notifications when
used with 3rd-party modules that were also using this interface.

New implementation requires notification event to be initialized
in order to register the handler:

    ngx_notify_init(&ngx_ping, ngx_ping_handler, cycle);
    ngx_notify_init(&ngx_pong, ngx_pong_handler, cycle);

and notification is triggered on the event and not on a handler:

    ngx_notify(&ngx_ping);
    ngx_notify(&ngx_pong);

Tested on Linux, FreeBSD, OS X and SmartOS.

Found with ThreadSanitizer.

Reported by Feng Li.

Signed-off-by: Piotr Sikora <piotrsikora at google.com>

diff -r c131f20c9562 -r e4241e448bc9 src/core/ngx_thread_pool.c
--- a/src/core/ngx_thread_pool.c
+++ b/src/core/ngx_thread_pool.c
@@ -99,6 +99,7 @@ ngx_module_t  ngx_thread_pool_module = {
 static ngx_str_t  ngx_thread_pool_default = ngx_string("default");
 
 static ngx_uint_t               ngx_thread_pool_task_id;
+static ngx_event_t              ngx_thread_pool_notify;
 static ngx_atomic_t             ngx_thread_pool_done_lock;
 static ngx_thread_pool_queue_t  ngx_thread_pool_done;
 
@@ -111,12 +112,6 @@ ngx_thread_pool_init(ngx_thread_pool_t *
     ngx_uint_t      n;
     pthread_attr_t  attr;
 
-    if (ngx_notify == NULL) {
-        ngx_log_error(NGX_LOG_ALERT, log, 0,
-               "the configured event method cannot be used with thread pools");
-        return NGX_ERROR;
-    }
-
     ngx_thread_pool_queue_init(&tp->queue);
 
     if (ngx_thread_mutex_create(&tp->mtx, log) != NGX_OK) {
@@ -349,7 +344,7 @@ ngx_thread_pool_cycle(void *data)
 
         ngx_unlock(&ngx_thread_pool_done_lock);
 
-        (void) ngx_notify(ngx_thread_pool_handler);
+        (void) ngx_notify(&ngx_thread_pool_notify);
     }
 }
 
@@ -588,10 +583,22 @@ ngx_thread_pool_init_worker(ngx_cycle_t 
     tcf = (ngx_thread_pool_conf_t *) ngx_get_conf(cycle->conf_ctx,
                                                   ngx_thread_pool_module);
 
-    if (tcf == NULL) {
+    if (tcf == NULL || tcf->pools.nelts == 0) {
         return NGX_OK;
     }
 
+    if (ngx_notify_init == NULL || ngx_notify == NULL) {
+        ngx_log_error(NGX_LOG_ALERT, cycle->log, 0,
+               "the configured event method cannot be used with thread pools");
+        return NGX_ERROR;
+    }
+
+    if (ngx_notify_init(&ngx_thread_pool_notify, ngx_thread_pool_handler, cycle)
+        != NGX_OK)
+    {
+        return NGX_ERROR;
+    }
+
     ngx_thread_pool_queue_init(&ngx_thread_pool_done);
 
     tpp = tcf->pools.elts;
@@ -622,7 +629,7 @@ ngx_thread_pool_exit_worker(ngx_cycle_t 
     tcf = (ngx_thread_pool_conf_t *) ngx_get_conf(cycle->conf_ctx,
                                                   ngx_thread_pool_module);
 
-    if (tcf == NULL) {
+    if (tcf == NULL || tcf->pools.nelts == 0) {
         return;
     }
 
@@ -631,4 +638,8 @@ ngx_thread_pool_exit_worker(ngx_cycle_t 
     for (i = 0; i < tcf->pools.nelts; i++) {
         ngx_thread_pool_destroy(tpp[i]);
     }
+
+    if (ngx_notify_close != NULL) {
+        ngx_notify_close(&ngx_thread_pool_notify);
+    }
 }
diff -r c131f20c9562 -r e4241e448bc9 src/event/modules/ngx_devpoll_module.c
--- a/src/event/modules/ngx_devpoll_module.c
+++ b/src/event/modules/ngx_devpoll_module.c
@@ -90,7 +90,9 @@ ngx_event_module_t  ngx_devpoll_module_c
         ngx_devpoll_del_event,             /* disable an event */
         NULL,                              /* add an connection */
         NULL,                              /* delete an connection */
+        NULL,                              /* init a notify */
         NULL,                              /* trigger a notify */
+        NULL,                              /* close a notify */
         ngx_devpoll_process_events,        /* process the events */
         ngx_devpoll_init,                  /* init the events */
         ngx_devpoll_done,                  /* done the events */
diff -r c131f20c9562 -r e4241e448bc9 src/event/modules/ngx_epoll_module.c
--- a/src/event/modules/ngx_epoll_module.c
+++ b/src/event/modules/ngx_epoll_module.c
@@ -103,8 +103,10 @@ typedef struct {
 
 static ngx_int_t ngx_epoll_init(ngx_cycle_t *cycle, ngx_msec_t timer);
 #if (NGX_HAVE_EVENTFD)
-static ngx_int_t ngx_epoll_notify_init(ngx_log_t *log);
+static ngx_int_t ngx_epoll_notify_init(ngx_event_t *notify_event,
+    ngx_event_handler_pt handler, ngx_cycle_t *cycle);
 static void ngx_epoll_notify_handler(ngx_event_t *ev);
+static void ngx_epoll_notify_close(ngx_event_t *notify_event);
 #endif
 #if (NGX_HAVE_EPOLLRDHUP)
 static void ngx_epoll_test_rdhup(ngx_cycle_t *cycle);
@@ -118,7 +120,7 @@ static ngx_int_t ngx_epoll_add_connectio
 static ngx_int_t ngx_epoll_del_connection(ngx_connection_t *c,
     ngx_uint_t flags);
 #if (NGX_HAVE_EVENTFD)
-static ngx_int_t ngx_epoll_notify(ngx_event_handler_pt handler);
+static ngx_int_t ngx_epoll_notify(ngx_event_t *notify_event);
 #endif
 static ngx_int_t ngx_epoll_process_events(ngx_cycle_t *cycle, ngx_msec_t timer,
     ngx_uint_t flags);
@@ -134,12 +136,6 @@ static int                  ep = -1;
 static struct epoll_event  *event_list;
 static ngx_uint_t           nevents;
 
-#if (NGX_HAVE_EVENTFD)
-static int                  notify_fd = -1;
-static ngx_event_t          notify_event;
-static ngx_connection_t     notify_conn;
-#endif
-
 #if (NGX_HAVE_FILE_AIO)
 
 int                         ngx_eventfd = -1;
@@ -189,9 +185,13 @@ ngx_event_module_t  ngx_epoll_module_ctx
         ngx_epoll_add_connection,        /* add an connection */
         ngx_epoll_del_connection,        /* delete an connection */
 #if (NGX_HAVE_EVENTFD)
+        ngx_epoll_notify_init,           /* init a notify */
         ngx_epoll_notify,                /* trigger a notify */
+        ngx_epoll_notify_close,          /* close a notify */
 #else
+        NULL,                            /* init a notify */
         NULL,                            /* trigger a notify */
+        NULL,                            /* close a notify */
 #endif
         ngx_epoll_process_events,        /* process the events */
         ngx_epoll_init,                  /* init the events */
@@ -335,12 +335,6 @@ ngx_epoll_init(ngx_cycle_t *cycle, ngx_m
             return NGX_ERROR;
         }
 
-#if (NGX_HAVE_EVENTFD)
-        if (ngx_epoll_notify_init(cycle->log) != NGX_OK) {
-            ngx_epoll_module_ctx.actions.notify = NULL;
-        }
-#endif
-
 #if (NGX_HAVE_FILE_AIO)
         ngx_epoll_aio_init(cycle, epcf);
 #endif
@@ -383,9 +377,17 @@ ngx_epoll_init(ngx_cycle_t *cycle, ngx_m
 #if (NGX_HAVE_EVENTFD)
 
 static ngx_int_t
-ngx_epoll_notify_init(ngx_log_t *log)
+ngx_epoll_notify_init(ngx_event_t *notify_event, ngx_event_handler_pt handler,
+    ngx_cycle_t *cycle)
 {
-    struct epoll_event  ee;
+    int                  notify_fd;
+    ngx_connection_t    *notify_conn;
+    struct epoll_event   ee;
+
+    notify_conn = ngx_pcalloc(cycle->pool, sizeof(ngx_connection_t));
+    if (notify_conn == NULL) {
+        return NGX_ERROR;
+    }
 
 #if (NGX_HAVE_SYS_EVENTFD_H)
     notify_fd = eventfd(0, 0);
@@ -394,31 +396,35 @@ ngx_epoll_notify_init(ngx_log_t *log)
 #endif
 
     if (notify_fd == -1) {
-        ngx_log_error(NGX_LOG_EMERG, log, ngx_errno, "eventfd() failed");
+        ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno, "eventfd() failed");
         return NGX_ERROR;
     }
 
-    ngx_log_debug1(NGX_LOG_DEBUG_EVENT, log, 0,
+    ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
                    "notify eventfd: %d", notify_fd);
 
-    notify_event.handler = ngx_epoll_notify_handler;
-    notify_event.log = log;
-    notify_event.active = 1;
+    ngx_memzero(notify_event, sizeof(ngx_event_t));
 
-    notify_conn.fd = notify_fd;
-    notify_conn.read = &notify_event;
-    notify_conn.log = log;
+    notify_event->data = notify_conn;
+    notify_event->handler = ngx_epoll_notify_handler;
+    notify_event->log = cycle->log;
+    notify_event->active = 1;
+
+    notify_conn->data = handler;
+    notify_conn->fd = notify_fd;
+    notify_conn->read = notify_event;
+    notify_conn->log = cycle->log;
 
     ee.events = EPOLLIN|EPOLLET;
-    ee.data.ptr = &notify_conn;
+    ee.data.ptr = notify_conn;
 
     if (epoll_ctl(ep, EPOLL_CTL_ADD, notify_fd, &ee) == -1) {
-        ngx_log_error(NGX_LOG_EMERG, log, ngx_errno,
+        ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno,
                       "epoll_ctl(EPOLL_CTL_ADD, eventfd) failed");
 
         if (close(notify_fd) == -1) {
-            ngx_log_error(NGX_LOG_ALERT, log, ngx_errno,
-                            "eventfd close() failed");
+            ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
+                          "close() eventfd %d failed", notify_fd);
         }
 
         return NGX_ERROR;
@@ -431,31 +437,45 @@ ngx_epoll_notify_init(ngx_log_t *log)
 static void
 ngx_epoll_notify_handler(ngx_event_t *ev)
 {
-    ssize_t               n;
-    uint64_t              count;
-    ngx_err_t             err;
-    ngx_event_handler_pt  handler;
+    ngx_connection_t      *c = ev->data;
+
+    ssize_t                n;
+    uint64_t               count;
+    ngx_err_t              err;
+    ngx_event_handler_pt   handler;
 
     if (++ev->index == NGX_MAX_UINT32_VALUE) {
         ev->index = 0;
 
-        n = read(notify_fd, &count, sizeof(uint64_t));
+        n = read(c->fd, &count, sizeof(uint64_t));
 
         err = ngx_errno;
 
         ngx_log_debug3(NGX_LOG_DEBUG_EVENT, ev->log, 0,
-                       "read() eventfd %d: %z count:%uL", notify_fd, n, count);
+                       "read() eventfd %d: %z count:%uL", c->fd, n, count);
 
         if ((size_t) n != sizeof(uint64_t)) {
             ngx_log_error(NGX_LOG_ALERT, ev->log, err,
-                          "read() eventfd %d failed", notify_fd);
+                          "read() eventfd %d failed", c->fd);
         }
     }
 
-    handler = ev->data;
+    handler = c->data;
     handler(ev);
 }
 
+
+static void
+ngx_epoll_notify_close(ngx_event_t *notify_event)
+{
+    ngx_connection_t  *c = notify_event->data;
+
+    if (close(c->fd) == -1) {
+        ngx_log_error(NGX_LOG_ALERT, notify_event->log, ngx_errno,
+                      "close() eventfd %d failed", c->fd);
+    }
+}
+
 #endif
 
 
@@ -536,17 +556,6 @@ ngx_epoll_done(ngx_cycle_t *cycle)
 
     ep = -1;
 
-#if (NGX_HAVE_EVENTFD)
-
-    if (close(notify_fd) == -1) {
-        ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
-                      "eventfd close() failed");
-    }
-
-    notify_fd = -1;
-
-#endif
-
 #if (NGX_HAVE_FILE_AIO)
 
     if (ngx_eventfd != -1) {
@@ -762,15 +771,14 @@ ngx_epoll_del_connection(ngx_connection_
 #if (NGX_HAVE_EVENTFD)
 
 static ngx_int_t
-ngx_epoll_notify(ngx_event_handler_pt handler)
+ngx_epoll_notify(ngx_event_t *notify_event)
 {
-    static uint64_t inc = 1;
+    static uint64_t    inc = 1;
+    ngx_connection_t  *c = notify_event->data;
 
-    notify_event.data = handler;
-
-    if ((size_t) write(notify_fd, &inc, sizeof(uint64_t)) != sizeof(uint64_t)) {
-        ngx_log_error(NGX_LOG_ALERT, notify_event.log, ngx_errno,
-                      "write() to eventfd %d failed", notify_fd);
+    if ((size_t) write(c->fd, &inc, sizeof(uint64_t)) != sizeof(uint64_t)) {
+        ngx_log_error(NGX_LOG_ALERT, notify_event->log, ngx_errno,
+                      "write() to eventfd %d failed", c->fd);
         return NGX_ERROR;
     }
 
diff -r c131f20c9562 -r e4241e448bc9 src/event/modules/ngx_eventport_module.c
--- a/src/event/modules/ngx_eventport_module.c
+++ b/src/event/modules/ngx_eventport_module.c
@@ -140,7 +140,9 @@ static ngx_int_t ngx_eventport_add_event
     ngx_uint_t flags);
 static ngx_int_t ngx_eventport_del_event(ngx_event_t *ev, ngx_int_t event,
     ngx_uint_t flags);
-static ngx_int_t ngx_eventport_notify(ngx_event_handler_pt handler);
+static ngx_int_t ngx_eventport_notify_init(ngx_event_t *notify_event,
+    ngx_event_handler_pt handler, ngx_cycle_t *cycle);
+static ngx_int_t ngx_eventport_notify(ngx_event_t *notify_event);
 static ngx_int_t ngx_eventport_process_events(ngx_cycle_t *cycle,
     ngx_msec_t timer, ngx_uint_t flags);
 
@@ -151,7 +153,6 @@ static int            ep = -1;
 static port_event_t  *event_list;
 static ngx_uint_t     nevents;
 static timer_t        event_timer = (timer_t) -1;
-static ngx_event_t    notify_event;
 
 static ngx_str_t      eventport_name = ngx_string("eventport");
 
@@ -181,7 +182,9 @@ ngx_event_module_t  ngx_eventport_module
         ngx_eventport_del_event,           /* disable an event */
         NULL,                              /* add an connection */
         NULL,                              /* delete an connection */
+        ngx_eventport_notify_init,         /* init a notify */
         ngx_eventport_notify,              /* trigger a notify */
+        NULL,                              /* close a notify */
         ngx_eventport_process_events,      /* process the events */
         ngx_eventport_init,                /* init the events */
         ngx_eventport_done,                /* done the events */
@@ -223,9 +226,6 @@ ngx_eventport_init(ngx_cycle_t *cycle, n
                           "port_create() failed");
             return NGX_ERROR;
         }
-
-        notify_event.active = 1;
-        notify_event.log = cycle->log;
     }
 
     if (nevents < epcf->events) {
@@ -418,12 +418,24 @@ ngx_eventport_del_event(ngx_event_t *ev,
 
 
 static ngx_int_t
-ngx_eventport_notify(ngx_event_handler_pt handler)
+ngx_eventport_notify_init(ngx_event_t *notify_event,
+    ngx_event_handler_pt handler, ngx_cycle_t *cycle)
 {
-    notify_event.handler = handler;
+    ngx_memzero(notify_event, sizeof(ngx_event_t));
 
-    if (port_send(ep, 0, &notify_event) != 0) {
-        ngx_log_error(NGX_LOG_ALERT, notify_event.log, ngx_errno,
+    notify_event->handler = handler;
+    notify_event->active = 1;
+    notify_event->log = cycle->log;
+
+    return NGX_OK;
+}
+
+
+static ngx_int_t
+ngx_eventport_notify(ngx_event_t *notify_event)
+{
+    if (port_send(ep, 0, notify_event) != 0) {
+        ngx_log_error(NGX_LOG_ALERT, notify_event->log, ngx_errno,
                       "port_send() failed");
         return NGX_ERROR;
     }
diff -r c131f20c9562 -r e4241e448bc9 src/event/modules/ngx_iocp_module.c
--- a/src/event/modules/ngx_iocp_module.c
+++ b/src/event/modules/ngx_iocp_module.c
@@ -64,7 +64,9 @@ ngx_event_module_t  ngx_iocp_module_ctx 
         NULL,                              /* disable an event */
         NULL,                              /* add an connection */
         ngx_iocp_del_connection,           /* delete an connection */
+        NULL,                              /* init a notify */
         NULL,                              /* trigger a notify */
+        NULL,                              /* close a notify */
         ngx_iocp_process_events,           /* process the events */
         ngx_iocp_init,                     /* init the events */
         ngx_iocp_done                      /* done the events */
diff -r c131f20c9562 -r e4241e448bc9 src/event/modules/ngx_kqueue_module.c
--- a/src/event/modules/ngx_kqueue_module.c
+++ b/src/event/modules/ngx_kqueue_module.c
@@ -18,7 +18,8 @@ typedef struct {
 
 static ngx_int_t ngx_kqueue_init(ngx_cycle_t *cycle, ngx_msec_t timer);
 #ifdef EVFILT_USER
-static ngx_int_t ngx_kqueue_notify_init(ngx_log_t *log);
+static ngx_int_t ngx_kqueue_notify_init(ngx_event_t *notify_event,
+    ngx_event_handler_pt handler, ngx_cycle_t *cycle);
 #endif
 static void ngx_kqueue_done(ngx_cycle_t *cycle);
 static ngx_int_t ngx_kqueue_add_event(ngx_event_t *ev, ngx_int_t event,
@@ -28,7 +29,7 @@ static ngx_int_t ngx_kqueue_del_event(ng
 static ngx_int_t ngx_kqueue_set_event(ngx_event_t *ev, ngx_int_t filter,
     ngx_uint_t flags);
 #ifdef EVFILT_USER
-static ngx_int_t ngx_kqueue_notify(ngx_event_handler_pt handler);
+static ngx_int_t ngx_kqueue_notify(ngx_event_t *notify_event);
 #endif
 static ngx_int_t ngx_kqueue_process_events(ngx_cycle_t *cycle, ngx_msec_t timer,
     ngx_uint_t flags);
@@ -45,11 +46,6 @@ static struct kevent  *change_list;
 static struct kevent  *event_list;
 static ngx_uint_t      max_changes, nchanges, nevents;
 
-#ifdef EVFILT_USER
-static ngx_event_t     notify_event;
-static struct kevent   notify_kev;
-#endif
-
 
 static ngx_str_t      kqueue_name = ngx_string("kqueue");
 
@@ -86,9 +82,13 @@ ngx_event_module_t  ngx_kqueue_module_ct
         NULL,                              /* add an connection */
         NULL,                              /* delete an connection */
 #ifdef EVFILT_USER
+        ngx_kqueue_notify_init,            /* init a notify */
         ngx_kqueue_notify,                 /* trigger a notify */
+        NULL,                              /* close a notify */
 #else
+        NULL,                              /* init a notify */
         NULL,                              /* trigger a notify */
+        NULL,                              /* close a notify */
 #endif
         ngx_kqueue_process_events,         /* process the events */
         ngx_kqueue_init,                   /* init the events */
@@ -132,12 +132,6 @@ ngx_kqueue_init(ngx_cycle_t *cycle, ngx_
                           "kqueue() failed");
             return NGX_ERROR;
         }
-
-#ifdef EVFILT_USER
-        if (ngx_kqueue_notify_init(cycle->log) != NGX_OK) {
-            return NGX_ERROR;
-        }
-#endif
     }
 
     if (max_changes < kcf->changes) {
@@ -230,27 +224,39 @@ ngx_kqueue_init(ngx_cycle_t *cycle, ngx_
 #ifdef EVFILT_USER
 
 static ngx_int_t
-ngx_kqueue_notify_init(ngx_log_t *log)
+ngx_kqueue_notify_init(ngx_event_t *notify_event, ngx_event_handler_pt handler,
+    ngx_cycle_t *cycle)
 {
-    notify_kev.ident = 0;
-    notify_kev.filter = EVFILT_USER;
-    notify_kev.data = 0;
-    notify_kev.flags = EV_ADD|EV_CLEAR;
-    notify_kev.fflags = 0;
-    notify_kev.udata = 0;
+    struct kevent  *notify_kev;
 
-    if (kevent(ngx_kqueue, &notify_kev, 1, NULL, 0, NULL) == -1) {
-        ngx_log_error(NGX_LOG_ALERT, log, ngx_errno,
+    notify_kev = ngx_pcalloc(cycle->pool, sizeof(struct kevent));
+    if (notify_kev == NULL) {
+        return NGX_ERROR;
+    }
+
+    notify_kev->ident = (uintptr_t) notify_event;
+    notify_kev->filter = EVFILT_USER;
+    notify_kev->data = 0;
+    notify_kev->flags = EV_ADD|EV_CLEAR;
+    notify_kev->fflags = 0;
+    notify_kev->udata = 0;
+
+    if (kevent(ngx_kqueue, notify_kev, 1, NULL, 0, NULL) == -1) {
+        ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno,
                       "kevent(EVFILT_USER, EV_ADD) failed");
         return NGX_ERROR;
     }
 
-    notify_event.active = 1;
-    notify_event.log = log;
+    ngx_memzero(notify_event, sizeof(ngx_event_t));
 
-    notify_kev.flags = 0;
-    notify_kev.fflags = NOTE_TRIGGER;
-    notify_kev.udata = NGX_KQUEUE_UDATA_T ((uintptr_t) &notify_event);
+    notify_event->data = notify_kev;
+    notify_event->handler = handler;
+    notify_event->active = 1;
+    notify_event->log = cycle->log;
+
+    notify_kev->flags = 0;
+    notify_kev->fflags = NOTE_TRIGGER;
+    notify_kev->udata = NGX_KQUEUE_UDATA_T ((uintptr_t) notify_event);
 
     return NGX_OK;
 }
@@ -478,12 +484,12 @@ ngx_kqueue_set_event(ngx_event_t *ev, ng
 #ifdef EVFILT_USER
 
 static ngx_int_t
-ngx_kqueue_notify(ngx_event_handler_pt handler)
+ngx_kqueue_notify(ngx_event_t *notify_event)
 {
-    notify_event.handler = handler;
+    struct kevent  *notify_kev = notify_event->data;
 
-    if (kevent(ngx_kqueue, &notify_kev, 1, NULL, 0, NULL) == -1) {
-        ngx_log_error(NGX_LOG_ALERT, notify_event.log, ngx_errno,
+    if (kevent(ngx_kqueue, notify_kev, 1, NULL, 0, NULL) == -1) {
+        ngx_log_error(NGX_LOG_ALERT, notify_event->log, ngx_errno,
                       "kevent(EVFILT_USER, NOTE_TRIGGER) failed");
         return NGX_ERROR;
     }
diff -r c131f20c9562 -r e4241e448bc9 src/event/modules/ngx_poll_module.c
--- a/src/event/modules/ngx_poll_module.c
+++ b/src/event/modules/ngx_poll_module.c
@@ -39,7 +39,9 @@ ngx_event_module_t  ngx_poll_module_ctx 
         ngx_poll_del_event,                /* disable an event */
         NULL,                              /* add an connection */
         NULL,                              /* delete an connection */
+        NULL,                              /* init a notify */
         NULL,                              /* trigger a notify */
+        NULL,                              /* close a notify */
         ngx_poll_process_events,           /* process the events */
         ngx_poll_init,                     /* init the events */
         ngx_poll_done                      /* done the events */
diff -r c131f20c9562 -r e4241e448bc9 src/event/modules/ngx_select_module.c
--- a/src/event/modules/ngx_select_module.c
+++ b/src/event/modules/ngx_select_module.c
@@ -47,7 +47,9 @@ ngx_event_module_t  ngx_select_module_ct
         ngx_select_del_event,              /* disable an event */
         NULL,                              /* add an connection */
         NULL,                              /* delete an connection */
+        NULL,                              /* init a notify */
         NULL,                              /* trigger a notify */
+        NULL,                              /* close a notify */
         ngx_select_process_events,         /* process the events */
         ngx_select_init,                   /* init the events */
         ngx_select_done                    /* done the events */
diff -r c131f20c9562 -r e4241e448bc9 src/event/modules/ngx_win32_select_module.c
--- a/src/event/modules/ngx_win32_select_module.c
+++ b/src/event/modules/ngx_win32_select_module.c
@@ -48,7 +48,9 @@ ngx_event_module_t  ngx_select_module_ct
         ngx_select_del_event,              /* disable an event */
         NULL,                              /* add an connection */
         NULL,                              /* delete an connection */
+        NULL,                              /* init a notify */
         NULL,                              /* trigger a notify */
+        NULL,                              /* close a notify */
         ngx_select_process_events,         /* process the events */
         ngx_select_init,                   /* init the events */
         ngx_select_done                    /* done the events */
diff -r c131f20c9562 -r e4241e448bc9 src/event/ngx_event.c
--- a/src/event/ngx_event.c
+++ b/src/event/ngx_event.c
@@ -170,7 +170,7 @@ ngx_event_module_t  ngx_event_core_modul
     ngx_event_core_create_conf,            /* create configuration */
     ngx_event_core_init_conf,              /* init configuration */
 
-    { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }
+    { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }
 };
 
 
diff -r c131f20c9562 -r e4241e448bc9 src/event/ngx_event.h
--- a/src/event/ngx_event.h
+++ b/src/event/ngx_event.h
@@ -184,7 +184,10 @@ typedef struct {
     ngx_int_t  (*add_conn)(ngx_connection_t *c);
     ngx_int_t  (*del_conn)(ngx_connection_t *c, ngx_uint_t flags);
 
-    ngx_int_t  (*notify)(ngx_event_handler_pt handler);
+    ngx_int_t  (*notify_init)(ngx_event_t *notify_event,
+                              ngx_event_handler_pt handler, ngx_cycle_t *cycle);
+    ngx_int_t  (*notify)(ngx_event_t *notify_event);
+    void       (*notify_close)(ngx_event_t *notify_event);
 
     ngx_int_t  (*process_events)(ngx_cycle_t *cycle, ngx_msec_t timer,
                                  ngx_uint_t flags);
@@ -416,7 +419,9 @@ extern ngx_uint_t            ngx_use_epo
 #define ngx_add_conn         ngx_event_actions.add_conn
 #define ngx_del_conn         ngx_event_actions.del_conn
 
+#define ngx_notify_init      ngx_event_actions.notify_init
 #define ngx_notify           ngx_event_actions.notify
+#define ngx_notify_close     ngx_event_actions.notify_close
 
 #define ngx_add_timer        ngx_event_add_timer
 #define ngx_del_timer        ngx_event_del_timer



More information about the nginx-devel mailing list