# HG changeset patch # User Piotr Sikora <piotrsik...@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 <piotrsik...@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 = ¬ify_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 = ¬ify_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, ¬ify_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, ¬ify_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) ¬ify_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, ¬ify_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 _______________________________________________ nginx-devel mailing list nginx-devel@nginx.org http://mailman.nginx.org/mailman/listinfo/nginx-devel