# HG changeset patch # User Igor Sysoev # Date 1159273212 0 # Node ID f30b1a75fd3b8cdb5f6efef0b0f05ddee4e6eeaf # Parent d488926182ea0701c2a8543fd6a2313c09c3af7d Solaris 10 event ports support diff --git a/auto/modules b/auto/modules --- a/auto/modules +++ b/auto/modules @@ -31,6 +31,14 @@ if [ $NGX_TEST_BUILD_DEVPOLL = YES ]; th CORE_SRCS="$CORE_SRCS $DEVPOLL_SRCS" fi + +if [ $NGX_TEST_BUILD_EVENTPORT = YES ]; then + have=NGX_HAVE_EVENTPORT . auto/have + have=NGX_TEST_BUILD_EVENTPORT . auto/have + EVENT_MODULES="$EVENT_MODULES $EVENTPORT_MODULE" + CORE_SRCS="$CORE_SRCS $EVENTPORT_SRCS" +fi + if [ $NGX_TEST_BUILD_EPOLL = YES ]; then have=NGX_HAVE_EPOLL . auto/have have=NGX_TEST_BUILD_EPOLL . auto/have diff --git a/auto/options b/auto/options --- a/auto/options +++ b/auto/options @@ -23,6 +23,7 @@ NGX_LD_OPT= CPU=NO NGX_TEST_BUILD_DEVPOLL=NO +NGX_TEST_BUILD_EVENTPORT=NO NGX_TEST_BUILD_EPOLL=NO NGX_TEST_BUILD_RTSIG=NO NGX_TEST_BUILD_SOLARIS_SENDFILEV=NO @@ -207,6 +208,7 @@ do --with-zlib-asm=*) ZLIB_ASM="$value" ;; --test-build-devpoll) NGX_TEST_BUILD_DEVPOLL=YES ;; + --test-build-eventport) NGX_TEST_BUILD_EVENTPORT=YES ;; --test-build-epoll) NGX_TEST_BUILD_EPOLL=YES ;; --test-build-rtsig) NGX_TEST_BUILD_RTSIG=YES ;; --test-build-solaris-sendfilev) NGX_TEST_BUILD_SOLARIS_SENDFILEV=YES ;; diff --git a/auto/os/solaris b/auto/os/solaris --- a/auto/os/solaris +++ b/auto/os/solaris @@ -39,3 +39,17 @@ if [ $ngx_found = yes ]; then CORE_SRCS="$CORE_SRCS $SOLARIS_SENDFILEV_SRCS" CORE_LIBS="$CORE_LIBS -lsendfile" fi + + +ngx_feature="event ports" +ngx_feature_name="NGX_HAVE_EVENTPORT" +ngx_feature_run=no +ngx_feature_incs="#include " +ngx_feature_libs= +ngx_feature_test="int n = port_create()" +. auto/feature + +if [ $ngx_found = yes ]; then + CORE_SRCS="$CORE_SRCS $EVENTPORT_SRCS" + EVENT_MODULES="$EVENT_MODULES $EVENTPORT_MODULE" +fi diff --git a/auto/sources b/auto/sources --- a/auto/sources +++ b/auto/sources @@ -95,6 +95,9 @@ KQUEUE_SRCS=src/event/modules/ngx_kqueue DEVPOLL_MODULE=ngx_devpoll_module DEVPOLL_SRCS=src/event/modules/ngx_devpoll_module.c +EVENTPORT_MODULE=ngx_eventport_module +EVENTPORT_SRCS=src/event/modules/ngx_eventport_module.c + EPOLL_MODULE=ngx_epoll_module EPOLL_SRCS=src/event/modules/ngx_epoll_module.c diff --git a/src/event/modules/ngx_eventport_module.c b/src/event/modules/ngx_eventport_module.c new file mode 100644 --- /dev/null +++ b/src/event/modules/ngx_eventport_module.c @@ -0,0 +1,593 @@ + +/* + * Copyright (C) Igor Sysoev + */ + + +#include +#include +#include + + +#if (NGX_TEST_BUILD_EVENTPORT) + +#define ushort_t u_short +#define uint_t u_int + +/* Solaris declarations */ + +#define PORT_SOURCE_AIO 1 +#define PORT_SOURCE_TIMER 2 +#define PORT_SOURCE_USER 3 +#define PORT_SOURCE_FD 4 +#define PORT_SOURCE_ALERT 5 +#define PORT_SOURCE_MQ 6 + +#define ETIME 64 + +#define SIGEV_PORT 4 + +typedef struct { + int portev_events; /* event data is source specific */ + ushort_t portev_source; /* event source */ + ushort_t portev_pad; /* port internal use */ + uintptr_t portev_object; /* source specific object */ + void *portev_user; /* user cookie */ +} port_event_t; + +typedef struct port_notify { + int portnfy_port; /* bind request(s) to port */ + void *portnfy_user; /* user defined */ +} port_notify_t; + +typedef struct itimerspec { /* definition per POSIX.4 */ + struct timespec it_interval; /* timer period */ + struct timespec it_value; /* timer expiration */ +} itimerspec_t; + +int port_create(void) +{ + return -1; +} + +int port_associate(int port, int source, uintptr_t object, int events, + void *user) +{ + return -1; +} + +int port_dissociate(int port, int source, uintptr_t object) +{ + return -1; +} + +int port_getn(int port, port_event_t list[], uint_t max, uint_t *nget, + struct timespec *timeout) +{ + return -1; +} + +int timer_create(clockid_t clock_id, struct sigevent *evp, timer_t *timerid) +{ + return -1; +} + +int timer_settime(timer_t timerid, int flags, const struct itimerspec *value, + struct itimerspec *ovalue) +{ + return -1; +} + +int timer_delete(timer_t timerid) +{ + return -1; +} + +#endif + + +typedef struct { + u_int events; +} ngx_eventport_conf_t; + + +static ngx_int_t ngx_eventport_init(ngx_cycle_t *cycle, ngx_msec_t timer); +static void ngx_eventport_done(ngx_cycle_t *cycle); +static ngx_int_t ngx_eventport_add_event(ngx_event_t *ev, int event, + u_int flags); +static ngx_int_t ngx_eventport_del_event(ngx_event_t *ev, int event, + u_int flags); +static ngx_int_t ngx_eventport_process_events(ngx_cycle_t *cycle, + ngx_msec_t timer, ngx_uint_t flags); + +static void *ngx_eventport_create_conf(ngx_cycle_t *cycle); +static char *ngx_eventport_init_conf(ngx_cycle_t *cycle, void *conf); + +static int ep = -1; +static port_event_t *event_list; +static u_int nevents; +static timer_t event_timer = -1; + +static ngx_str_t eventport_name = ngx_string("eventport"); + + +static ngx_command_t ngx_eventport_commands[] = { + + { ngx_string("eventport_events"), + NGX_EVENT_CONF|NGX_CONF_TAKE1, + ngx_conf_set_num_slot, + 0, + offsetof(ngx_eventport_conf_t, events), + NULL }, + + ngx_null_command +}; + + +ngx_event_module_t ngx_eventport_module_ctx = { + &eventport_name, + ngx_eventport_create_conf, /* create configuration */ + ngx_eventport_init_conf, /* init configuration */ + + { + ngx_eventport_add_event, /* add an event */ + ngx_eventport_del_event, /* delete an event */ + ngx_eventport_add_event, /* enable an event */ + ngx_eventport_del_event, /* disable an event */ + NULL, /* add an connection */ + NULL, /* delete an connection */ + NULL, /* process the changes */ + ngx_eventport_process_events, /* process the events */ + ngx_eventport_init, /* init the events */ + ngx_eventport_done, /* done the events */ + } + +}; + +ngx_module_t ngx_eventport_module = { + NGX_MODULE_V1, + &ngx_eventport_module_ctx, /* module context */ + ngx_eventport_commands, /* module directives */ + NGX_EVENT_MODULE, /* module type */ + NULL, /* init master */ + NULL, /* init module */ + NULL, /* init process */ + NULL, /* init thread */ + NULL, /* exit thread */ + NULL, /* exit process */ + NULL, /* exit master */ + NGX_MODULE_V1_PADDING +}; + + +static ngx_int_t +ngx_eventport_init(ngx_cycle_t *cycle, ngx_msec_t timer) +{ + port_notify_t pn; + struct itimerspec its; + struct sigevent sev; + ngx_eventport_conf_t *epcf; + + epcf = ngx_event_get_conf(cycle->conf_ctx, ngx_eventport_module); + + if (ep == -1) { + ep = port_create(); + + if (ep == -1) { + ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno, + "port_create() failed"); + return NGX_ERROR; + } + } + + if (nevents < epcf->events) { + if (event_list) { + ngx_free(event_list); + } + + event_list = ngx_alloc(sizeof(port_event_t) * epcf->events, + cycle->log); + if (event_list == NULL) { + return NGX_ERROR; + } + } + + ngx_event_flags = NGX_USE_EVENTPORT_EVENT; + + if (timer) { + ngx_memzero(&pn, sizeof(port_notify_t)); + pn.portnfy_port = ep; + + ngx_memzero(&sev, sizeof(struct sigevent)); + sev.sigev_notify = SIGEV_PORT; +#if !(NGX_TEST_BUILD_EVENTPORT) + sev.sigev_value.sival_ptr = &pn; +#endif + + if (timer_create(CLOCK_REALTIME, &sev, &event_timer) == -1) { + ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno, + "timer_create() failed"); + return NGX_ERROR; + } + + its.it_interval.tv_sec = timer / 1000; + its.it_interval.tv_nsec = (timer % 1000) * 1000000; + its.it_value.tv_sec = timer / 1000; + its.it_value.tv_nsec = (timer % 1000) * 1000000; + + if (timer_settime(event_timer, 0, &its, NULL) == -1) { + ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno, + "timer_settime() failed"); + return NGX_ERROR; + } + + ngx_event_flags |= NGX_USE_TIMER_EVENT; + } + + nevents = epcf->events; + + ngx_io = ngx_os_io; + + ngx_event_actions = ngx_eventport_module_ctx.actions; + + return NGX_OK; +} + + +static void +ngx_eventport_done(ngx_cycle_t *cycle) +{ + if (event_timer != -1) { + if (timer_delete(event_timer) == -1) { + ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno, + "timer_delete() failed"); + } + + event_timer = -1; + } + + if (close(ep) == -1) { + ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno, + "close() event port failed"); + } + + ep = -1; + + ngx_free(event_list); + + event_list = NULL; + nevents = 0; +} + + +static ngx_int_t +ngx_eventport_add_event(ngx_event_t *ev, int event, u_int flags) +{ + int events, prev; + ngx_event_t *e; + ngx_connection_t *c; + + c = ev->data; + + events = event; + + if (event == NGX_READ_EVENT) { + e = c->write; + prev = POLLOUT; +#if (NGX_READ_EVENT != POLLIN) + events = POLLIN; +#endif + + } else { + e = c->read; + prev = POLLIN; +#if (NGX_WRITE_EVENT != POLLOUT) + events = POLLOUT; +#endif + } + + if (e->oneshot) { + events |= prev; + } + + ngx_log_debug2(NGX_LOG_DEBUG_EVENT, ev->log, 0, + "eventport add event: fd:%d ev:%04Xd", c->fd, events); + + if (port_associate(ep, PORT_SOURCE_FD, c->fd, events, + (void *) ((uintptr_t) ev | ev->instance)) + == -1) + { + ngx_log_error(NGX_LOG_ALERT, ev->log, ngx_errno, + "port_associate() failed"); + return NGX_ERROR; + } + + ev->active = 1; + ev->oneshot = 1; + + return NGX_OK; +} + + +static ngx_int_t +ngx_eventport_del_event(ngx_event_t *ev, int event, u_int flags) +{ + ngx_event_t *e; + ngx_connection_t *c; + + /* + * when the file descriptor is closed, the event port automatically + * dissociates it from the port, so we do not need to dissociate explicity + * the event before the closing the file descriptor + */ + + if (flags & NGX_CLOSE_EVENT) { + ev->active = 0; + ev->oneshot = 0; + return NGX_OK; + } + + c = ev->data; + + if (event == NGX_READ_EVENT) { + e = c->write; + event = POLLOUT; + + } else { + e = c->read; + event = POLLIN; + } + + if (e->oneshot) { + ngx_log_debug2(NGX_LOG_DEBUG_EVENT, ev->log, 0, + "eventport change event: fd:%d ev:%04Xd", c->fd, event); + + if (port_associate(ep, PORT_SOURCE_FD, c->fd, event, + (void *) ((uintptr_t) ev | ev->instance)) + == -1) + { + ngx_log_error(NGX_LOG_ALERT, ev->log, ngx_errno, + "port_associate() failed"); + return NGX_ERROR; + } + + } else { + ngx_log_debug1(NGX_LOG_DEBUG_EVENT, ev->log, 0, + "eventport del event: fd:%d", c->fd); + + if (port_dissociate(ep, PORT_SOURCE_FD, c->fd) == -1) { + ngx_log_error(NGX_LOG_ALERT, ev->log, ngx_errno, + "port_dissociate() failed"); + return NGX_ERROR; + } + } + + ev->active = 0; + ev->oneshot = 0; + + return NGX_OK; +} + + +ngx_int_t +ngx_eventport_process_events(ngx_cycle_t *cycle, ngx_msec_t timer, + ngx_uint_t flags) +{ + int n, revents; + u_int events; + ngx_err_t err; + ngx_int_t instance; + ngx_uint_t i, level; + ngx_event_t *ev, *rev, *wev, **queue; + ngx_connection_t *c; + struct timespec ts, *tp; + + if (timer == NGX_TIMER_INFINITE) { + tp = NULL; + + } else { + ts.tv_sec = timer / 1000; + ts.tv_nsec = (timer % 1000) * 1000000; + tp = &ts; + } + + ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0, + "eventport timer: %M", timer); + + events = 1; + + n = port_getn(ep, event_list, nevents, &events, tp); + + err = ngx_errno; + + if (flags & NGX_UPDATE_TIME) { + ngx_time_update(0, 0); + } + + if (n == -1) { + if (err == ETIME) { + if (timer != NGX_TIMER_INFINITE) { + return NGX_OK; + } + + ngx_log_error(NGX_LOG_ALERT, cycle->log, 0, + "port_getn() returned no events without timeout"); + return NGX_ERROR; + } + + level = (err == NGX_EINTR) ? NGX_LOG_INFO : NGX_LOG_ALERT; + ngx_log_error(level, cycle->log, err, "port_getn() failed"); + return NGX_ERROR; + } + + if (events == 0) { + if (timer != NGX_TIMER_INFINITE) { + return NGX_OK; + } + + ngx_log_error(NGX_LOG_ALERT, cycle->log, 0, + "port_getn() returned no events without timeout"); + return NGX_ERROR; + } + + ngx_mutex_lock(ngx_posted_events_mutex); + + for (i = 0; i < events; i++) { + + if (event_list[i].portev_source == PORT_SOURCE_TIMER) { + ngx_time_update(0, 0); + continue; + } + + ev = event_list[i].portev_user; + + switch (event_list[i].portev_source) { + + case PORT_SOURCE_FD: + + instance = (uintptr_t) ev & 1; + ev = (ngx_event_t *) ((uintptr_t) ev & (uintptr_t) ~1); + + if (ev->closed || ev->instance != instance) { + + /* + * the stale event from a file descriptor + * that was just closed in this iteration + */ + + ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0, + "eventport: stale event %p", ev); + continue; + } + + revents = event_list[i].portev_events; + + ngx_log_debug2(NGX_LOG_DEBUG_EVENT, cycle->log, 0, + "eventport: fd:%d, ev:%04Xd", + event_list[i].portev_object, revents); + + if (revents & (POLLERR|POLLHUP|POLLNVAL)) { + ngx_log_error(NGX_LOG_ALERT, cycle->log, 0, + "prot_getn() error fd:%d ev:%04Xd", + event_list[i].portev_object, revents); + } + + if (revents & ~(POLLIN|POLLOUT|POLLERR|POLLHUP|POLLNVAL)) { + ngx_log_error(NGX_LOG_ALERT, cycle->log, 0, + "strange port_getn() events fd:%d ev:%04Xd", + event_list[i].portev_object, revents); + } + + if ((revents & (POLLERR|POLLHUP|POLLNVAL)) + && (revents & (POLLIN|POLLOUT)) == 0) + { + /* + * if the error events were returned without POLLIN or POLLOUT, + * then add these flags to handle the events at least in one + * active handler + */ + + revents |= POLLIN|POLLOUT; + } + + c = ev->data; + rev = c->read; + wev = c->write; + + rev->active = 0; + wev->active = 0; + + if (revents & POLLIN) { + + if ((flags & NGX_POST_THREAD_EVENTS) && !rev->accept) { + rev->posted_ready = 1; + + } else { + rev->ready = 1; + } + + if (flags & NGX_POST_EVENTS) { + queue = (ngx_event_t **) (rev->accept ? + &ngx_posted_accept_events : &ngx_posted_events); + + ngx_locked_post_event(rev, queue); + + } else { + rev->handler(rev); + } + + if (rev->accept) { + if (ngx_use_accept_mutex) { + ngx_accept_events = 1; + continue; + } + + if (port_associate(ep, PORT_SOURCE_FD, c->fd, POLLIN, + (void *) ((uintptr_t) ev | ev->instance)) + == -1) + { + ngx_log_error(NGX_LOG_ALERT, ev->log, ngx_errno, + "port_associate() failed"); + return NGX_ERROR; + } + } + } + + if (revents & POLLOUT) { + + if (flags & NGX_POST_THREAD_EVENTS) { + wev->posted_ready = 1; + + } else { + wev->ready = 1; + } + + if (flags & NGX_POST_EVENTS) { + ngx_locked_post_event(wev, &ngx_posted_events); + + } else { + wev->handler(wev); + } + } + + continue; + + default: + ngx_log_error(NGX_LOG_ALERT, cycle->log, 0, + "unexpected even_port object %d", + event_list[i].portev_object); + continue; + } + } + + ngx_mutex_unlock(ngx_posted_events_mutex); + + return NGX_OK; +} + + +static void * +ngx_eventport_create_conf(ngx_cycle_t *cycle) +{ + ngx_eventport_conf_t *epcf; + + epcf = ngx_palloc(cycle->pool, sizeof(ngx_eventport_conf_t)); + if (epcf == NULL) { + return NGX_CONF_ERROR; + } + + epcf->events = NGX_CONF_UNSET; + + return epcf; +} + + +static char * +ngx_eventport_init_conf(ngx_cycle_t *cycle, void *conf) +{ + ngx_eventport_conf_t *epcf = conf; + + ngx_conf_init_uint_value(epcf->events, 32); + + return NGX_CONF_OK; +} diff --git a/src/event/ngx_event.c b/src/event/ngx_event.c --- a/src/event/ngx_event.c +++ b/src/event/ngx_event.c @@ -13,6 +13,7 @@ extern ngx_module_t ngx_kqueue_module; +extern ngx_module_t ngx_eventport_module; extern ngx_module_t ngx_devpoll_module; extern ngx_module_t ngx_epoll_module; extern ngx_module_t ngx_rtsig_module; @@ -49,6 +50,7 @@ ngx_atomic_t *ngx_connection_cou ngx_atomic_t *ngx_accept_mutex_ptr; ngx_shmtx_t ngx_accept_mutex; ngx_uint_t ngx_use_accept_mutex; +ngx_uint_t ngx_accept_events; ngx_uint_t ngx_accept_mutex_held; ngx_msec_t ngx_accept_mutex_delay; ngx_int_t ngx_accept_disabled; @@ -314,19 +316,25 @@ ngx_handle_read_event(ngx_event_t *rev, return NGX_OK; } - } else if (ngx_event_flags & NGX_USE_ONESHOT_EVENT) { + } else if (ngx_event_flags & NGX_USE_EVENTPORT_EVENT) { /* event ports */ - if (!rev->active) { - if (ngx_add_event(rev, NGX_READ_EVENT, NGX_ONESHOT_EVENT) - == NGX_ERROR) - { + if (!rev->active && !rev->ready) { + if (ngx_add_event(rev, NGX_READ_EVENT, 0) == NGX_ERROR) { return NGX_ERROR; } + + return NGX_OK; } - return NGX_OK; + if (rev->oneshot && !rev->ready) { + if (ngx_del_event(rev, NGX_READ_EVENT, 0) == NGX_ERROR) { + return NGX_ERROR; + } + + return NGX_OK; + } } /* aio, iocp, rtsig */ @@ -341,7 +349,7 @@ ngx_handle_write_event(ngx_event_t *wev, ngx_connection_t *c; if (lowat) { - c = (ngx_connection_t *) wev->data; + c = wev->data; if (ngx_send_lowat(c, lowat) == NGX_ERROR) { return NGX_ERROR; @@ -387,19 +395,25 @@ ngx_handle_write_event(ngx_event_t *wev, return NGX_OK; } - } else if (ngx_event_flags & NGX_USE_ONESHOT_EVENT) { + } else if (ngx_event_flags & NGX_USE_EVENTPORT_EVENT) { /* event ports */ - if (!wev->active) { - if (ngx_add_event(wev, NGX_WRITE_EVENT, NGX_ONESHOT_EVENT) - == NGX_ERROR) - { + if (!wev->active && !wev->ready) { + if (ngx_add_event(wev, NGX_WRITE_EVENT, 0) == NGX_ERROR) { return NGX_ERROR; } + + return NGX_OK; } - return NGX_OK; + if (wev->oneshot && wev->ready) { + if (ngx_del_event(wev, NGX_WRITE_EVENT, 0) == NGX_ERROR) { + return NGX_ERROR; + } + + return NGX_OK; + } } /* aio, iocp, rtsig */ @@ -1198,7 +1212,7 @@ ngx_event_init_conf(ngx_cycle_t *cycle, event_module = ngx_modules[i]->ctx; if (ngx_strcmp(event_module->name->data, event_core_name.data) - == 0) + == 0) { continue; } diff --git a/src/event/ngx_event.h b/src/event/ngx_event.h --- a/src/event/ngx_event.h +++ b/src/event/ngx_event.h @@ -41,8 +41,6 @@ struct ngx_event_s { unsigned accept:1; - unsigned oneshot:1; - /* used to detect the stale events in kqueue, rt signals and epoll */ unsigned instance:1; @@ -57,6 +55,8 @@ struct ngx_event_s { /* the ready event; in aio mode 0 means that no operation can be posted */ unsigned ready:1; + unsigned oneshot:1; + /* aio operation is complete */ unsigned complete:1; @@ -224,7 +224,7 @@ extern ngx_event_actions_t ngx_event_a /* * The event filter is deleted after a notification without an additional - * syscall: kqueue, epoll, Solaris 10's event ports. + * syscall: kqueue, epoll. */ #define NGX_USE_ONESHOT_EVENT 0x00000002 @@ -286,14 +286,17 @@ extern ngx_event_actions_t ngx_event_a */ #define NGX_USE_TIMER_EVENT 0x00000800 +/* + * All event filters on file descriptor are deleted after a notification: + * Solaris 10's event ports. + */ +#define NGX_USE_EVENTPORT_EVENT 0x00001000 + /* * The event filter is deleted before the closing file. - * Has no meaning for select, poll, epoll. - * - * kqueue: kqueue deletes event filters for file that closed - * so we need only to delete filters in user-level batch array + * Has no meaning for select, poll, kqueue, epoll. * /dev/poll: we need to flush POLLREMOVE event before closing file */ @@ -335,7 +338,7 @@ extern ngx_event_actions_t ngx_event_a #define NGX_DISABLE_EVENT EV_DISABLE -#elif (NGX_HAVE_DEVPOLL) +#elif (NGX_HAVE_DEVPOLL || NGX_HAVE_EVENTPORT) #define NGX_READ_EVENT POLLIN #define NGX_WRITE_EVENT POLLOUT @@ -446,6 +449,7 @@ extern ngx_atomic_t *ngx_connec extern ngx_atomic_t *ngx_accept_mutex_ptr; extern ngx_shmtx_t ngx_accept_mutex; extern ngx_uint_t ngx_use_accept_mutex; +extern ngx_uint_t ngx_accept_events; extern ngx_uint_t ngx_accept_mutex_held; extern ngx_msec_t ngx_accept_mutex_delay; extern ngx_int_t ngx_accept_disabled; diff --git a/src/event/ngx_event_accept.c b/src/event/ngx_event_accept.c --- a/src/event/ngx_event_accept.c +++ b/src/event/ngx_event_accept.c @@ -56,6 +56,8 @@ ngx_event_accept(ngx_event_t *ev) err = ngx_socket_errno; if (err == NGX_EAGAIN) { + ngx_log_debug0(NGX_LOG_DEBUG_EVENT, ev->log, err, + "accept() not ready"); return; } @@ -264,7 +266,10 @@ ngx_trylock_accept_mutex(ngx_cycle_t *cy ngx_log_debug0(NGX_LOG_DEBUG_EVENT, cycle->log, 0, "accept mutex locked"); - if (ngx_accept_mutex_held && !(ngx_event_flags & NGX_USE_RTSIG_EVENT)) { + if (ngx_accept_mutex_held + && ngx_accept_events == 0 + && !(ngx_event_flags & NGX_USE_RTSIG_EVENT)) + { return NGX_OK; } @@ -273,11 +278,15 @@ ngx_trylock_accept_mutex(ngx_cycle_t *cy return NGX_ERROR; } + ngx_accept_events = 0; ngx_accept_mutex_held = 1; return NGX_OK; } + ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0, + "accept mutex lock failed: %ui", ngx_accept_mutex_held); + if (ngx_accept_mutex_held) { if (ngx_disable_accept_events(cycle) == NGX_ERROR) { return NGX_ERROR; diff --git a/src/os/unix/ngx_solaris_config.h b/src/os/unix/ngx_solaris_config.h --- a/src/os/unix/ngx_solaris_config.h +++ b/src/os/unix/ngx_solaris_config.h @@ -74,6 +74,11 @@ #endif +#if (NGX_HAVE_EVENTPORT) +#include +#endif + + #ifndef NGX_HAVE_INHERITED_NONBLOCK #define NGX_HAVE_INHERITED_NONBLOCK 1 #endif