diff --git a/auto/os/freebsd b/auto/os/freebsd index b8c524ae3..dfe4ea748 100644 --- a/auto/os/freebsd +++ b/auto/os/freebsd @@ -4,8 +4,8 @@ CORE_DEPS="$UNIX_DEPS $FREEBSD_DEPS" CORE_SRCS="$UNIX_SRCS $FREEBSD_SRCS" -# __FreeBSD_version is the best way to learn when -# some capability appeared or became safe to use +# __FreeBSD_version is the best way to determine whether +# some capability exists and is safe to use version=`grep "#define __FreeBSD_version" /usr/include/osreldate.h \ | sed -e 's/^.* \(.*\)$/\1/'` diff --git a/src/event/modules/ngx_aio_module.c b/src/event/modules/ngx_aio_module.c index 2f9c09b21..24516a423 100644 --- a/src/event/modules/ngx_aio_module.c +++ b/src/event/modules/ngx_aio_module.c @@ -13,7 +13,7 @@ static int ngx_aio_init(ngx_cycle_t *cycle); static void ngx_aio_done(ngx_cycle_t *cycle); static int ngx_aio_add_event(ngx_event_t *ev, int event, u_int flags); static int ngx_aio_del_event(ngx_event_t *ev, int event, u_int flags); -static int ngx_aio_del_connection(ngx_connection_t *c); +static int ngx_aio_del_connection(ngx_connection_t *c, u_int flags); static int ngx_aio_process_events(ngx_log_t *log); @@ -96,7 +96,7 @@ static int ngx_aio_del_event(ngx_event_t *ev, int event, u_int flags) } -static int ngx_aio_del_connection(ngx_connection_t *c) +static int ngx_aio_del_connection(ngx_connection_t *c, u_int flags) { int rc; diff --git a/src/event/modules/ngx_iocp_module.c b/src/event/modules/ngx_iocp_module.c index 9612c9ab9..e95a81974 100644 --- a/src/event/modules/ngx_iocp_module.c +++ b/src/event/modules/ngx_iocp_module.c @@ -13,7 +13,7 @@ static int ngx_iocp_init(ngx_cycle_t *cycle); static void ngx_iocp_done(ngx_cycle_t *cycle); static int ngx_iocp_add_event(ngx_event_t *ev, int event, u_int key); -static int ngx_iocp_del_connection(ngx_connection_t *c); +static int ngx_iocp_del_connection(ngx_connection_t *c, u_int flags); static int ngx_iocp_process_events(ngx_log_t *log); static void *ngx_iocp_create_conf(ngx_cycle_t *cycle); static char *ngx_iocp_init_conf(ngx_cycle_t *cycle, void *conf); @@ -154,7 +154,7 @@ static int ngx_iocp_add_event(ngx_event_t *ev, int event, u_int key) } -static int ngx_iocp_del_connection(ngx_connection_t *c) +static int ngx_iocp_del_connection(ngx_connection_t *c, u_int flags) { if (CancelIo((HANDLE) c->fd) == 0) { ngx_log_error(NGX_LOG_ALERT, c->log, ngx_errno, "CancelIo() failed"); diff --git a/src/event/modules/ngx_poll_module.c b/src/event/modules/ngx_poll_module.c index 9c5f8e12f..c8ea197b6 100644 --- a/src/event/modules/ngx_poll_module.c +++ b/src/event/modules/ngx_poll_module.c @@ -13,7 +13,7 @@ static int ngx_poll_init(ngx_cycle_t *cycle); static void ngx_poll_done(ngx_cycle_t *cycle); static int ngx_poll_add_event(ngx_event_t *ev, int event, u_int flags); static int ngx_poll_del_event(ngx_event_t *ev, int event, u_int flags); -static int ngx_poll_process_events(ngx_log_t *log); +int ngx_poll_process_events(ngx_log_t *log); static struct pollfd *event_list; @@ -245,7 +245,7 @@ static int ngx_poll_del_event(ngx_event_t *ev, int event, u_int flags) } -static int ngx_poll_process_events(ngx_log_t *log) +int ngx_poll_process_events(ngx_log_t *log) { int ready; ngx_int_t i, j, nready, found; @@ -257,13 +257,19 @@ static int ngx_poll_process_events(ngx_log_t *log) ngx_connection_t *c; struct timeval tv; - timer = ngx_event_find_timer(); - ngx_old_elapsed_msec = ngx_elapsed_msec; + if (ngx_event_flags & NGX_OVERFLOW_EVENT) { + timer = 0; - if (timer == 0) { - timer = (ngx_msec_t) INFTIM; + } else { + timer = ngx_event_find_timer(); + + if (timer == 0) { + timer = (ngx_msec_t) INFTIM; + } } + ngx_old_elapsed_msec = ngx_elapsed_msec; + #if (NGX_DEBUG0) for (i = 0; i < nevents; i++) { ngx_log_debug3(NGX_LOG_DEBUG_EVENT, log, 0, "poll: %d: fd:%d ev:%04X", @@ -309,6 +315,11 @@ static int ngx_poll_process_events(ngx_log_t *log) } } + if (timer == 0 && ready == 0) { + /* the overflowed rt signals queue has been drained */ + return NGX_OK; + } + nready = 0; for (i = 0; i < nevents && ready; i++) { @@ -431,5 +442,5 @@ static int ngx_poll_process_events(ngx_log_t *log) ngx_event_expire_timers((ngx_msec_t) delta); } - return NGX_OK; + return nready; } diff --git a/src/event/modules/ngx_rtsig_module.c b/src/event/modules/ngx_rtsig_module.c index 5c1536fc6..32c544a8d 100644 --- a/src/event/modules/ngx_rtsig_module.c +++ b/src/event/modules/ngx_rtsig_module.c @@ -15,15 +15,9 @@ #define SIGRTMIN 33 #define si_fd __spare__[0] -int sigwaitinfo(const sigset_t *set, siginfo_t *info); - int sigtimedwait(const sigset_t *set, siginfo_t *info, const struct timespec *timeout); -int sigwaitinfo(const sigset_t *set, siginfo_t *info) -{ - return -1; -} int sigtimedwait(const sigset_t *set, siginfo_t *info, const struct timespec *timeout) @@ -39,11 +33,14 @@ typedef struct { } ngx_rtsig_conf_t; +extern ngx_event_module_t ngx_poll_module_ctx; + static int ngx_rtsig_init(ngx_cycle_t *cycle); static void ngx_rtsig_done(ngx_cycle_t *cycle); static int ngx_rtsig_add_connection(ngx_connection_t *c); -static int ngx_rtsig_del_connection(ngx_connection_t *c); +static int ngx_rtsig_del_connection(ngx_connection_t *c, u_int flags); static int ngx_rtsig_process_events(ngx_log_t *log); +static int ngx_rtsig_process_overlow(ngx_log_t *log); static void *ngx_rtsig_create_conf(ngx_cycle_t *cycle); static char *ngx_rtsig_init_conf(ngx_cycle_t *cycle, void *conf); @@ -100,6 +97,10 @@ static int ngx_rtsig_init(ngx_cycle_t *cycle) { ngx_rtsig_conf_t *rtscf; + if (ngx_poll_module_ctx.actions.init(cycle) == NGX_ERROR) { + return NGX_ERROR; + } + rtscf = ngx_event_get_conf(cycle->conf_ctx, ngx_rtsig_module); sigemptyset(&set); @@ -124,6 +125,7 @@ static int ngx_rtsig_init(ngx_cycle_t *cycle) static void ngx_rtsig_done(ngx_cycle_t *cycle) { + ngx_poll_module_ctx.actions.done(cycle); } @@ -169,8 +171,16 @@ static int ngx_rtsig_add_connection(ngx_connection_t *c) } -static int ngx_rtsig_del_connection(ngx_connection_t *c) +static int ngx_rtsig_del_connection(ngx_connection_t *c, u_int flags) { + if (!(flags & NGX_CLOSE_EVENT)) { + if (fcntl(c->fd, F_SETFL, O_RDWR|O_NONBLOCK) == -1) { + ngx_log_error(NGX_LOG_ALERT, c->log, ngx_errno, + "fcntl(O_RDWR|O_NONBLOCK) failed"); + return NGX_ERROR; + } + } + c->read->active = 0; c->write->active = 0; @@ -188,7 +198,7 @@ int ngx_rtsig_process_events(ngx_log_t *log) ngx_cycle_t **cycle; siginfo_t si; struct timeval tv; - struct timespec ts; + struct timespec ts, *tp; struct sigaction sa; ngx_connection_t *c; ngx_epoch_msec_t delta; @@ -200,15 +210,17 @@ int ngx_rtsig_process_events(ngx_log_t *log) if (timer) { ts.tv_sec = timer / 1000; ts.tv_nsec = (timer % 1000) * 1000000; + tp = &ts; + + } else { + tp = NULL; } ngx_log_debug1(NGX_LOG_DEBUG_EVENT, log, 0, "rtsig timer: %d", timer); - if (timer) { - signo = sigtimedwait(&set, &si, &ts); - } else { - signo = sigwaitinfo(&set, &si); - } + /* Linux sigwaitinfo() is sigtimedwait() with the NULL timeout pointer */ + + signo = sigtimedwait(&set, &si, tp); if (signo == -1) { err = ngx_errno; @@ -222,10 +234,9 @@ int ngx_rtsig_process_events(ngx_log_t *log) delta = ngx_elapsed_msec; ngx_elapsed_msec = tv.tv_sec * 1000 + tv.tv_usec / 1000 - ngx_start_msec; - if (signo == -1) { + if (err) { ngx_log_error((err == NGX_EINTR) ? NGX_LOG_INFO : NGX_LOG_ALERT, - log, err, - timer ? "sigtimedwait() failed" : "sigwaitinfo() failed"); + log, err, "sigtimedwait() failed"); return NGX_ERROR; } @@ -267,6 +278,8 @@ int ngx_rtsig_process_events(ngx_log_t *log) "signal queue overflowed: " "SIGIO, fd:%d, band:%X", si.si_fd, si.si_band); + /* TODO: flush all the used RT signals */ + ngx_memzero(&sa, sizeof(struct sigaction)); sa.sa_handler = SIG_DFL; sigemptyset(&sa.sa_mask); @@ -275,11 +288,17 @@ int ngx_rtsig_process_events(ngx_log_t *log) "sigaction(%d, SIG_DFL) failed", rtscf->signo); } + ngx_event_actions = ngx_poll_module_ctx.actions; + ngx_event_actions.process = ngx_rtsig_process_overflow; + ngx_event_flags = NGX_OVERFLOW_EVENT + |NGX_USE_LEVEL_EVENT|NGX_USE_ONESHOT_EVENT; + + /* STUB: add events. WHAT to do with fcntl()s ? */ + + } else { ngx_log_error(NGX_LOG_ALERT, log, 0, - timer ? "sigtimedwait() returned unexpected signal: %d": - "sigwaitinfo() returned unexpected signal: %d", - signo); + "sigtimedwait() returned unexpected signal: %d", signo); return NGX_ERROR; } @@ -291,6 +310,17 @@ int ngx_rtsig_process_events(ngx_log_t *log) } +static int ngx_rtsig_process_overlow(ngx_log_t *log) +{ + if (ngx_poll_module_ctx.actions.process(log) == NGX_OK) { + ngx_event_actions = ngx_rtsig_module_ctx.actions; + ngx_event_flags = NGX_USE_SIGIO_EVENT; + } + + return NGX_OK; +} + + static void *ngx_rtsig_create_conf(ngx_cycle_t *cycle) { ngx_rtsig_conf_t *rtscf; diff --git a/src/event/ngx_event.h b/src/event/ngx_event.h index 493f8d1f7..1a05751a1 100644 --- a/src/event/ngx_event.h +++ b/src/event/ngx_event.h @@ -163,7 +163,7 @@ typedef struct { int (*disable)(ngx_event_t *ev, int event, u_int flags); int (*add_conn)(ngx_connection_t *c); - int (*del_conn)(ngx_connection_t *c); + int (*del_conn)(ngx_connection_t *c, u_int flags); int (*process)(ngx_log_t *log); int (*init)(ngx_cycle_t *cycle); @@ -215,17 +215,22 @@ extern ngx_event_actions_t ngx_event_actions; */ #define NGX_USE_SIGIO_EVENT 0x00000040 +/* + * The alternative event method after the rt signals queue overflow. + */ +#define NGX_OVERFLOW_EVENT 0x00000080 + /* * No need to add or delete the event filters - overlapped, aio_read, * aioread, io_submit. */ -#define NGX_USE_AIO_EVENT 0x00000080 +#define NGX_USE_AIO_EVENT 0x00000100 /* * Need to add socket or handle only once - i/o completion port. * It also requires HAVE_AIO and NGX_USE_AIO_EVENT to be set. */ -#define NGX_USE_IOCP_EVENT 0x00000100 +#define NGX_USE_IOCP_EVENT 0x00000200 diff --git a/src/http/modules/proxy/ngx_http_proxy_handler.c b/src/http/modules/proxy/ngx_http_proxy_handler.c index 59b1c06e8..68e9032c2 100644 --- a/src/http/modules/proxy/ngx_http_proxy_handler.c +++ b/src/http/modules/proxy/ngx_http_proxy_handler.c @@ -532,7 +532,7 @@ void ngx_http_proxy_close_connection(ngx_http_proxy_ctx_t *p) /* TODO: move connection to the connection pool */ if (ngx_del_conn) { - ngx_del_conn(c); + ngx_del_conn(c, NGX_CLOSE_EVENT); } else { if (c->read->active) { diff --git a/src/http/ngx_http_request.c b/src/http/ngx_http_request.c index d93c61c2b..530b69ce8 100644 --- a/src/http/ngx_http_request.c +++ b/src/http/ngx_http_request.c @@ -1538,7 +1538,7 @@ void ngx_http_close_connection(ngx_connection_t *c) } if (ngx_del_conn) { - ngx_del_conn(c); + ngx_del_conn(c, NGX_CLOSE_EVENT); } else { if (c->read->active || c->read->disabled) {