# HG changeset patch # User Igor Sysoev # Date 1081110729 0 # Node ID 6b91bfbc412398b8c524d20bb0eb82e3de4679cf # Parent 4b1a3a4acc60fbf8a7e9fdb985fb4eb523f658c9 nginx-0.0.3-2004-04-05-00:32:09 import diff --git a/auto/cc b/auto/cc --- a/auto/cc +++ b/auto/cc @@ -2,7 +2,7 @@ case $CC in *gcc*) - # gcc 2.95.4, 3.3.2 + # gcc 2.7.2.3, 2.95.4, 3.3.2, 3.4 # optimization #CFLAGS="$CFLAGS -O2 -fomit-frame-pointer" diff --git a/auto/lib/md5/conf b/auto/lib/md5/conf --- a/auto/lib/md5/conf +++ b/auto/lib/md5/conf @@ -32,7 +32,8 @@ if [ $MD5 != NONE ]; then *) LINK_DEPS="$LINK_DEPS $MD5/libmd5.a" - CORE_LIBS="$CORE_LIBS -L $MD5 -lmd5" + CORE_LIBS="$CORE_LIBS $MD5/libmd5.a" + #CORE_LIBS="$CORE_LIBS -L $MD5 -lmd5" ;; esac diff --git a/auto/lib/pcre/conf b/auto/lib/pcre/conf --- a/auto/lib/pcre/conf +++ b/auto/lib/pcre/conf @@ -31,7 +31,8 @@ if [ $PCRE != NONE ]; then have=HAVE_PCRE . auto/have CORE_DEPS="$CORE_DEPS $PCRE/pcre.h" LINK_DEPS="$LINK_DEPS $PCRE/.libs/libpcre.a" - CORE_LIBS="$CORE_LIBS -L $PCRE/.libs -lpcre" + CORE_LIBS="$CORE_LIBS $PCRE/.libs/libpcre.a" + #CORE_LIBS="$CORE_LIBS -L $PCRE/.libs -lpcre" ;; esac diff --git a/auto/lib/zlib/conf b/auto/lib/zlib/conf --- a/auto/lib/zlib/conf +++ b/auto/lib/zlib/conf @@ -26,7 +26,8 @@ if [ $ZLIB != NONE ]; then *) LINK_DEPS="$LINK_DEPS $ZLIB/libz.a" - CORE_LIBS="$CORE_LIBS -L $ZLIB -lz" + CORE_LIBS="$CORE_LIBS $ZLIB/libz.a" + #CORE_LIBS="$CORE_LIBS -L $ZLIB -lz" ;; esac diff --git a/auto/sources b/auto/sources --- a/auto/sources +++ b/auto/sources @@ -52,12 +52,14 @@ EVENT_INCS="src/event src/event/modules" EVENT_DEPS="src/event/ngx_event.h \ src/event/ngx_event_timer.h \ + src/event/ngx_event_posted.h \ src/event/ngx_event_busy_lock.h \ src/event/ngx_event_connect.h \ src/event/ngx_event_pipe.h" EVENT_SRCS="src/event/ngx_event.c \ src/event/ngx_event_timer.c \ + src/event/ngx_event_posted.c \ src/event/ngx_event_busy_lock.c \ src/event/ngx_event_accept.c \ src/event/ngx_event_connect.c \ diff --git a/src/core/ngx_conf_file.h b/src/core/ngx_conf_file.h --- a/src/core/ngx_conf_file.h +++ b/src/core/ngx_conf_file.h @@ -176,12 +176,12 @@ char *ngx_conf_check_num_bounds(ngx_conf } #define ngx_conf_init_size_value(conf, default) \ - if (conf == NGX_CONF_UNSET) { \ + if (conf == NGX_CONF_UNSET_SIZE) { \ conf = default; \ } #define ngx_conf_init_msec_value(conf, default) \ - if (conf == NGX_CONF_UNSET) { \ + if (conf == NGX_CONF_UNSET_MSEC) { \ conf = default; \ } diff --git a/src/event/modules/ngx_epoll_module.c b/src/event/modules/ngx_epoll_module.c --- a/src/event/modules/ngx_epoll_module.c +++ b/src/event/modules/ngx_epoll_module.c @@ -168,10 +168,11 @@ static int ngx_epoll_init(ngx_cycle_t *c ngx_event_actions = ngx_epoll_module_ctx.actions; #if (HAVE_CLEAR_EVENT) - ngx_event_flags = NGX_USE_CLEAR_EVENT; + ngx_event_flags = NGX_USE_CLEAR_EVENT #else - ngx_event_flags = NGX_USE_LEVEL_EVENT; + ngx_event_flags = NGX_USE_LEVEL_EVENT #endif + |NGX_HAVE_INSTANCE_EVENT; return NGX_OK; } @@ -257,7 +258,7 @@ static int ngx_epoll_del_event(ngx_event /* * when the file descriptor is closed the epoll automatically deletes * it from its queue so we do not need to delete explicity the event - * before the closing the file descriptor. + * before the closing the file descriptor */ if (flags & NGX_CLOSE_EVENT) { @@ -339,21 +340,36 @@ static int ngx_epoll_del_connection(ngx_ int ngx_epoll_process_events(ngx_cycle_t *cycle) { - int events; - ngx_int_t instance, i; - size_t n; - ngx_msec_t timer; - ngx_err_t err; - struct timeval tv; - ngx_connection_t *c; - ngx_epoch_msec_t delta; - + int events; + ngx_int_t instance, i; + ngx_uint_t lock, expire; + size_t n; + ngx_msec_t timer; + ngx_err_t err; + struct timeval tv; + ngx_connection_t *c; + ngx_epoch_msec_t delta; timer = ngx_event_find_timer(); ngx_old_elapsed_msec = ngx_elapsed_msec; if (timer == 0) { timer = (ngx_msec_t) -1; + expire = 0; + + } else { + expire = 1; + } + + if (ngx_accept_mutex) { + if (ngx_trylock_accept_mutex(cycle) == NGX_ERROR) { + return NGX_ERROR; + } + + if (ngx_accept_mutex_held == 0 && timer > ngx_accept_mutex_delay) { + timer = ngx_accept_mutex_delay; + expire = 0; + } } ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0, @@ -382,6 +398,7 @@ int ngx_epoll_process_events(ngx_cycle_t if (events == 0) { ngx_log_error(NGX_LOG_ALERT, cycle->log, 0, "epoll_wait() returned no events without timeout"); + ngx_accept_mutex_unlock(); return NGX_ERROR; } } @@ -389,9 +406,17 @@ int ngx_epoll_process_events(ngx_cycle_t if (err) { ngx_log_error((err == NGX_EINTR) ? NGX_LOG_INFO : NGX_LOG_ALERT, cycle->log, err, "epoll_wait() failed"); + ngx_accept_mutex_unlock(); return NGX_ERROR; } + if (ngx_mutex_lock(ngx_posted_events_mutex) == NGX_ERROR) { + ngx_accept_mutex_unlock(); + return NGX_ERROR; + } + + lock = 1; + for (i = 0; i < events; i++) { c = event_list[i].data.ptr; @@ -434,25 +459,68 @@ int ngx_epoll_process_events(ngx_cycle_t c->fd, event_list[i].events); } + if ((event_list[i].events & (EPOLLOUT|EPOLLERR|EPOLLHUP)) + && c->write->active) + { + c->write->ready = 1; + + if (!ngx_threaded && !ngx_accept_mutex_held) { + c->write->event_handler(c->write); + + } else { + ngx_post_event(c->write); + } + } + + /* + * EPOLLIN must be handled after EPOLLOUT because we use + * the optimization to avoid the unnecessary mutex locking/unlocking + * if the accept event is the last one. + */ + if ((event_list[i].events & (EPOLLIN|EPOLLERR|EPOLLHUP)) && c->read->active) { c->read->ready = 1; - c->read->event_handler(c->read); - } + + if (!ngx_threaded && !ngx_accept_mutex_held) { + c->read->event_handler(c->read); + + } else if (!c->read->accept) { + ngx_post_event(c->read); + + } else { + ngx_mutex_unlock(ngx_posted_events_mutex); - if ((event_list[i].events & (EPOLLOUT|EPOLLERR|EPOLLHUP)) - && c->write->active) - { - c->write->ready = 1; - c->write->event_handler(c->write); + c->read->event_handler(c->read); + + if (i + 1 == events) { + lock = 0; + break; + } + + if (ngx_mutex_lock(ngx_posted_events_mutex) == NGX_ERROR) { + ngx_accept_mutex_unlock(); + return NGX_ERROR; + } + } } } - if (timer != (ngx_msec_t) -1 && delta) { + if (lock) { + ngx_mutex_unlock(ngx_posted_events_mutex); + } + + ngx_accept_mutex_unlock(); + + if (expire && delta) { ngx_event_expire_timers((ngx_msec_t) delta); } + if (!ngx_threaded) { + ngx_event_process_posted(cycle); + } + return NGX_OK; } diff --git a/src/event/modules/ngx_kqueue_module.c b/src/event/modules/ngx_kqueue_module.c --- a/src/event/modules/ngx_kqueue_module.c +++ b/src/event/modules/ngx_kqueue_module.c @@ -22,9 +22,6 @@ static int ngx_kqueue_add_event(ngx_even static int ngx_kqueue_del_event(ngx_event_t *ev, int event, u_int flags); static int ngx_kqueue_set_event(ngx_event_t *ev, int filter, u_int flags); static int ngx_kqueue_process_events(ngx_cycle_t *cycle); -#if (NGX_THREADS) -static void ngx_kqueue_thread_handler(ngx_event_t *ev); -#endif static void *ngx_kqueue_create_conf(ngx_cycle_t *cycle); static char *ngx_kqueue_init_conf(ngx_cycle_t *cycle, void *conf); @@ -71,9 +68,6 @@ ngx_event_module_t ngx_kqueue_module_ct NULL, /* add an connection */ NULL, /* delete an connection */ ngx_kqueue_process_events, /* process the events */ -#if (NGX_THREADS0) - ngx_kqueue_thread_handler, /* process an event by thread */ -#endif ngx_kqueue_init, /* init the events */ ngx_kqueue_done /* done the events */ } @@ -161,6 +155,7 @@ static int ngx_kqueue_init(ngx_cycle_t * #if (HAVE_LOWAT_EVENT) |NGX_HAVE_LOWAT_EVENT #endif + |NGX_HAVE_INSTANCE_EVENT |NGX_HAVE_KQUEUE_EVENT; return NGX_OK; @@ -346,8 +341,8 @@ static int ngx_kqueue_set_event(ngx_even static ngx_int_t ngx_kqueue_process_events(ngx_cycle_t *cycle) { int events; - ngx_int_t i; - ngx_uint_t instance; + ngx_int_t i, instance; + ngx_uint_t lock, expire; ngx_err_t err; ngx_msec_t timer; ngx_event_t *ev; @@ -364,23 +359,25 @@ static ngx_int_t ngx_kqueue_process_even /* * TODO: if timer is 0 and any worker thread is still busy - * then set 1 second timeout + * then set 500 ms timeout */ #endif ngx_old_elapsed_msec = ngx_elapsed_msec; + expire = 1; if (ngx_accept_mutex) { if (ngx_trylock_accept_mutex(cycle) == NGX_ERROR) { return NGX_ERROR; } -#if 1 - if (ngx_accept_mutex_held == 0 && timer == 0) { - /* STUB */ timer = 500; + if (ngx_accept_mutex_held == 0 + && (timer == 0 || timer > ngx_accept_mutex_delay)) + { + timer = ngx_accept_mutex_delay; + expire = 0; } -#endif } if (timer) { @@ -390,6 +387,7 @@ static ngx_int_t ngx_kqueue_process_even } else { tp = NULL; + expire = 0; } ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0, @@ -441,6 +439,8 @@ static ngx_int_t ngx_kqueue_process_even return NGX_ERROR; } + lock = 1; + for (i = 0; i < events; i++) { ngx_log_debug6(NGX_LOG_DEBUG_EVENT, cycle->log, 0, @@ -517,106 +517,49 @@ static ngx_int_t ngx_kqueue_process_even continue; } - - if (ngx_threaded || ngx_accept_mutex_held) { - - if (ev->accept) { - ngx_mutex_unlock(ngx_posted_events_mutex); - - ev->event_handler(ev); + if (!ngx_threaded && !ngx_accept_mutex_held) { + ev->event_handler(ev); + continue; + } - if (ngx_mutex_lock(ngx_posted_events_mutex) == NGX_ERROR) { - ngx_accept_mutex_unlock(); - return NGX_ERROR; - } - - } else { - ev->next = (ngx_event_t *) ngx_posted_events; - ngx_posted_events = ev; - } - + if (!ev->accept) { + ngx_post_event(ev); continue; } + ngx_mutex_unlock(ngx_posted_events_mutex); + ev->event_handler(ev); + + if (i + 1 == events) { + lock = 0; + break; + } + + if (ngx_mutex_lock(ngx_posted_events_mutex) == NGX_ERROR) { + ngx_accept_mutex_unlock(); + return NGX_ERROR; + } } - ngx_mutex_unlock(ngx_posted_events_mutex); + if (lock) { + ngx_mutex_unlock(ngx_posted_events_mutex); + } ngx_accept_mutex_unlock(); - if (timer && delta) { + if (expire && delta) { ngx_event_expire_timers((ngx_msec_t) delta); } - if (ngx_threaded) { - return NGX_OK; - } - - for ( ;; ) { - - ev = (ngx_event_t *) ngx_posted_events; - - ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0, - "kevent: posted event " PTR_FMT, ev); - - if (ev == NULL) { - break; - } - - ngx_posted_events = ev->next; - - if ((!ev->posted && !ev->active) - || ev->instance != ev->returned_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, - "kevent: stale event " PTR_FMT, ev); - continue; - } - - if (ev->posted) { - ev->posted = 0; - } - - ev->event_handler(ev); + if (!ngx_threaded) { + ngx_event_process_posted(cycle); } return NGX_OK; } -#if (NGX_THREADS) - -static void ngx_kqueue_thread_handler(ngx_event_t *ev) -{ - if ((!ev->posted && !ev->active) - || ev->instance != ev->returned_instance) - { - /* - * the stale event from a file descriptor - * that was just closed in this iteration - */ - - ngx_log_debug1(NGX_LOG_DEBUG_EVENT, ev->log, 0, - "kevent: stale event " PTR_FMT, ev); - return; - } - - if (ev->posted) { - ev->posted = 0; - } - - ev->event_handler(ev); -} - -#endif - - static void *ngx_kqueue_create_conf(ngx_cycle_t *cycle) { ngx_kqueue_conf_t *kcf; diff --git a/src/event/modules/ngx_rtsig_module.c b/src/event/modules/ngx_rtsig_module.c --- a/src/event/modules/ngx_rtsig_module.c +++ b/src/event/modules/ngx_rtsig_module.c @@ -117,7 +117,7 @@ static int ngx_rtsig_init(ngx_cycle_t *c ngx_event_actions = ngx_rtsig_module_ctx.actions; - ngx_event_flags = NGX_USE_SIGIO_EVENT; + ngx_event_flags = NGX_USE_SIGIO_EVENT|NGX_HAVE_INSTANCE_EVENT; return NGX_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 @@ -49,12 +49,8 @@ ngx_event_actions_t ngx_ev ngx_atomic_t *ngx_accept_mutex_ptr; ngx_atomic_t *ngx_accept_mutex; ngx_uint_t ngx_accept_mutex_held; - +ngx_msec_t ngx_accept_mutex_delay; -ngx_thread_volatile ngx_event_t *ngx_posted_events; -#if (NGX_THREADS) -ngx_mutex_t *ngx_posted_events_mutex; -#endif static ngx_str_t events_name = ngx_string("events"); @@ -114,6 +110,13 @@ static ngx_command_t ngx_event_core_com offsetof(ngx_event_conf_t, accept_mutex), NULL }, + { ngx_string("accept_mutex_delay"), + NGX_EVENT_CONF|NGX_CONF_TAKE1, + ngx_conf_set_msec_slot, + 0, + offsetof(ngx_event_conf_t, accept_mutex_delay), + NULL }, + ngx_null_command }; @@ -186,10 +189,12 @@ static ngx_int_t ngx_event_process_init( ccf = (ngx_core_conf_t *) ngx_get_conf(cycle->conf_ctx, ngx_core_module); + ecf = ngx_event_get_conf(cycle->conf_ctx, ngx_event_core_module); if (ccf->worker_processes > 1 && ngx_accept_mutex_ptr) { ngx_accept_mutex = ngx_accept_mutex_ptr; ngx_accept_mutex_held = 1; + ngx_accept_mutex_delay = ecf->accept_mutex_delay; } #if (NGX_THREADS) @@ -202,8 +207,6 @@ static ngx_int_t ngx_event_process_init( return NGX_ERROR; } - ecf = ngx_event_get_conf(cycle->conf_ctx, ngx_event_core_module); - cycle->connection_n = ecf->connections; for (m = 0; ngx_modules[m]; m++) { @@ -525,6 +528,7 @@ static void *ngx_event_create_conf(ngx_c ecf->use = NGX_CONF_UNSET; ecf->multi_accept = NGX_CONF_UNSET; ecf->accept_mutex = NGX_CONF_UNSET; + ecf->accept_mutex_delay = NGX_CONF_UNSET_MSEC; ecf->name = (void *) NGX_CONF_UNSET; return ecf; @@ -598,6 +602,7 @@ static char *ngx_event_init_conf(ngx_cyc ngx_conf_init_value(ecf->multi_accept, 0); ngx_conf_init_value(ecf->accept_mutex, 1); + ngx_conf_init_msec_value(ecf->accept_mutex_delay, 500); return NGX_CONF_OK; } 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 @@ -65,6 +65,7 @@ struct ngx_event_s { unsigned char write:1; /* used to detect the stale events in kqueue, rt signals and epoll */ + unsigned char use_instance:1; unsigned char instance:1; unsigned char returned_instance:1; @@ -79,7 +80,7 @@ struct ngx_event_s { unsigned char posted:1; /* the ready event; in aio mode 0 means that no operation can be posted */ - unsigned char ready:1; + unsigned short ready:1; /* aio operation is complete */ unsigned short complete:1; @@ -196,59 +197,65 @@ extern ngx_event_actions_t ngx_event_a * The event filter requires to read/write the whole data - * select, poll, /dev/poll, kqueue, epoll. */ -#define NGX_USE_LEVEL_EVENT 0x00000001 +#define NGX_USE_LEVEL_EVENT 0x00000001 /* * The event filter is deleted after a notification without an additional * syscall - select, poll, kqueue, epoll. */ -#define NGX_USE_ONESHOT_EVENT 0x00000002 +#define NGX_USE_ONESHOT_EVENT 0x00000002 /* * The event filter notifies only the changes and an initial level - * kqueue, epoll. */ -#define NGX_USE_CLEAR_EVENT 0x00000004 +#define NGX_USE_CLEAR_EVENT 0x00000004 /* * The event filter has kqueue features - the eof flag, errno, * available data, etc. */ -#define NGX_HAVE_KQUEUE_EVENT 0x00000008 +#define NGX_HAVE_KQUEUE_EVENT 0x00000008 /* * The event filter supports low water mark - kqueue's NOTE_LOWAT. * kqueue in FreeBSD 4.1-4.2 has no NOTE_LOWAT so we need a separate flag. */ -#define NGX_HAVE_LOWAT_EVENT 0x00000010 +#define NGX_HAVE_LOWAT_EVENT 0x00000010 + +/* + * The event filter allows to pass instance information to check stale events - + * kqueue, epoll, rt signals. + */ +#define NGX_HAVE_INSTANCE_EVENT 0x00000020 /* * The event filter notifies only the changes (the edges) * but not an initial level - early epoll patches. */ -#define NGX_USE_EDGE_EVENT 0x00000020 +#define NGX_USE_EDGE_EVENT 0x00000040 /* * No need to add or delete the event filters - rt signals. */ -#define NGX_USE_SIGIO_EVENT 0x00000040 +#define NGX_USE_SIGIO_EVENT 0x00000080 /* * The alternative event method after the rt signals queue overflow. */ -#define NGX_OVERFLOW_EVENT 0x00000080 +#define NGX_OVERFLOW_EVENT 0x00000100 /* * No need to add or delete the event filters - overlapped, aio_read, * aioread, io_submit. */ -#define NGX_USE_AIO_EVENT 0x00000100 +#define NGX_USE_AIO_EVENT 0x00000200 /* * 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 0x00000200 +#define NGX_USE_IOCP_EVENT 0x00000400 @@ -380,6 +387,8 @@ typedef struct { ngx_flag_t multi_accept; ngx_flag_t accept_mutex; + ngx_msec_t accept_mutex_delay; + u_char *name; } ngx_event_conf_t; @@ -395,14 +404,11 @@ typedef struct { -extern ngx_thread_volatile ngx_event_t *ngx_posted_events; -#if (NGX_THREADS) -extern ngx_mutex_t *ngx_posted_events_mutex; -#endif - extern ngx_atomic_t *ngx_accept_mutex_ptr; extern ngx_atomic_t *ngx_accept_mutex; extern ngx_uint_t ngx_accept_mutex_held; +extern ngx_msec_t ngx_accept_mutex_delay; + #define ngx_accept_mutex_unlock() \ if (ngx_accept_mutex_held) { \ @@ -437,6 +443,7 @@ int ngx_event_post_acceptex(ngx_listenin #include +#include #include #if (WIN32) 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 @@ -218,11 +218,15 @@ void ngx_event_accept(ngx_event_t *ev) c->sockaddr = sa; c->socklen = len; - rev->instance = (u_char) !instance; - rev->returned_instance = (u_char) rinstance; + if (ngx_event_flags & NGX_HAVE_INSTANCE_EVENT) { + rev->use_instance = 1; + rev->instance = (u_char) !instance; + rev->returned_instance = (u_char) rinstance; - wev->instance = (u_char) !instance; - wev->returned_instance = (u_char) winstance; + wev->use_instance = 1; + wev->instance = (u_char) !instance; + wev->returned_instance = (u_char) winstance; + } rev->index = NGX_INVALID_INDEX; wev->index = NGX_INVALID_INDEX; @@ -302,7 +306,9 @@ void ngx_event_accept(ngx_event_t *ev) ngx_int_t ngx_trylock_accept_mutex(ngx_cycle_t *cycle) { - if (*ngx_accept_mutex == 0 && ngx_atomic_cmp_set(ngx_accept_mutex, 0, 1)) { + if (*ngx_accept_mutex == 0 + && ngx_atomic_cmp_set(ngx_accept_mutex, 0, ngx_pid)) + { ngx_log_debug0(NGX_LOG_DEBUG_EVENT, cycle->log, 0, "accept mutex locked"); diff --git a/src/event/ngx_event_connect.c b/src/event/ngx_event_connect.c --- a/src/event/ngx_event_connect.c +++ b/src/event/ngx_event_connect.c @@ -11,7 +11,7 @@ int ngx_event_connect_peer(ngx_peer_connection_t *pc) { int rc; - ngx_uint_t instance; + ngx_uint_t instance, rinstance, winstance; u_int event; time_t now; ngx_err_t err; @@ -156,11 +156,23 @@ int ngx_event_connect_peer(ngx_peer_conn #endif instance = rev->instance; + rinstance = rev->returned_instance; + winstance = wev->returned_instance; ngx_memzero(c, sizeof(ngx_connection_t)); ngx_memzero(rev, sizeof(ngx_event_t)); ngx_memzero(wev, sizeof(ngx_event_t)); + if (ngx_event_flags & NGX_HAVE_INSTANCE_EVENT) { + rev->use_instance = 1; + rev->instance = (u_char) !instance; + rev->returned_instance = (u_char) rinstance; + + wev->use_instance = 1; + wev->instance = (u_char) !instance; + wev->returned_instance = (u_char) winstance; + } + rev->index = NGX_INVALID_INDEX; wev->index = NGX_INVALID_INDEX; @@ -171,9 +183,6 @@ int ngx_event_connect_peer(ngx_peer_conn c->write = wev; wev->write = 1; - rev->instance = (u_char) !instance; - wev->instance = (u_char) !instance; - c->log = pc->log; rev->log = pc->log; wev->log = pc->log; diff --git a/src/event/ngx_event_posted.c b/src/event/ngx_event_posted.c new file mode 100644 --- /dev/null +++ b/src/event/ngx_event_posted.c @@ -0,0 +1,76 @@ + +#include +#include +#include + + +ngx_thread_volatile ngx_event_t *ngx_posted_events; +#if (NGX_THREADS) +ngx_mutex_t *ngx_posted_events_mutex; +#endif + + +void ngx_event_process_posted(ngx_cycle_t *cycle) +{ + ngx_event_t *ev; + + for ( ;; ) { + + ev = (ngx_event_t *) ngx_posted_events; + + ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0, + "posted event " PTR_FMT, ev); + + if (ev == NULL) { + return; + } + + ngx_posted_events = ev->next; + + if ((!ev->posted && !ev->active) + || (ev->use_instance && ev->instance != ev->returned_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, + "stale posted event " PTR_FMT, ev); + continue; + } + + if (ev->posted) { + ev->posted = 0; + } + + ev->event_handler(ev); + } +} + + +#if (NGX_THREADS) + +void ngx_event_thread_handler(ngx_event_t *ev) +{ + if ((!ev->posted && !ev->active) + || (ev->use_instance && ev->instance != ev->returned_instance)) + { + /* + * the stale event from a file descriptor + * that was just closed in this iteration + */ + + ngx_log_debug1(NGX_LOG_DEBUG_EVENT, ev->log, 0, + "kevent: stale event " PTR_FMT, ev); + return; + } + + if (ev->posted) { + ev->posted = 0; + } + + ev->event_handler(ev); +} + +#endif diff --git a/src/event/ngx_event_posted.h b/src/event/ngx_event_posted.h new file mode 100644 --- /dev/null +++ b/src/event/ngx_event_posted.h @@ -0,0 +1,28 @@ +#ifndef _NGX_EVENT_POSTED_H_INCLUDED_ +#define _NGX_EVENT_POSTED_H_INCLUDED_ + + +#include +#include +#include + + +#define ngx_post_event(ev) \ + ev->next = (ngx_event_t *) ngx_posted_events; \ + ngx_posted_events = ev; \ + ev->posted = 1; + + +void ngx_event_process_posted(ngx_cycle_t *cycle); +#if (NGX_THREADS) +void ngx_event_thread_handler(ngx_event_t *ev); +#endif + + +extern ngx_thread_volatile ngx_event_t *ngx_posted_events; +#if (NGX_THREADS) +extern ngx_mutex_t *ngx_posted_events_mutex; +#endif + + +#endif /* _NGX_EVENT_POSTED_H_INCLUDED_ */ diff --git a/src/event/ngx_event_timer.c b/src/event/ngx_event_timer.c --- a/src/event/ngx_event_timer.c +++ b/src/event/ngx_event_timer.c @@ -42,18 +42,14 @@ ngx_msec_t ngx_event_find_timer(void) return 0; } -#if (NGX_THREADS) if (ngx_mutex_lock(ngx_event_timer_mutex) == NGX_ERROR) { return NGX_TIMER_ERROR; } -#endif node = ngx_rbtree_min((ngx_rbtree_t *) ngx_event_timer_rbtree, &ngx_event_timer_sentinel); -#if (NGX_THREADS) ngx_mutex_unlock(ngx_event_timer_mutex); -#endif return (ngx_msec_t) (node->key * NGX_TIMER_RESOLUTION - @@ -75,18 +71,14 @@ void ngx_event_expire_timers(ngx_msec_t break; } -#if (NGX_THREADS) if (ngx_mutex_lock(ngx_event_timer_mutex) == NGX_ERROR) { return; } -#endif node = ngx_rbtree_min((ngx_rbtree_t *) ngx_event_timer_rbtree, &ngx_event_timer_sentinel); -#if (NGX_THREADS) ngx_mutex_unlock(ngx_event_timer_mutex); -#endif if ((ngx_msec_t) node->key <= (ngx_msec_t) (ngx_old_elapsed_msec + timer) / NGX_TIMER_RESOLUTION) @@ -106,9 +98,16 @@ void ngx_event_expire_timers(ngx_msec_t ev->timedout = 1; } -#if (NGX_THREADS) - /* STUB: post event */ -#endif + if (ngx_threaded) { + if (ngx_mutex_lock(ngx_posted_events_mutex) == NGX_ERROR) { + return; + } + + ngx_post_event(ev); + + ngx_mutex_unlock(ngx_posted_events_mutex); + continue; + } ev->event_handler(ev); continue; diff --git a/src/http/modules/proxy/ngx_http_proxy_handler.c b/src/http/modules/proxy/ngx_http_proxy_handler.c --- a/src/http/modules/proxy/ngx_http_proxy_handler.c +++ b/src/http/modules/proxy/ngx_http_proxy_handler.c @@ -369,6 +369,9 @@ static int ngx_http_proxy_handler(ngx_ht void ngx_http_proxy_check_broken_connection(ngx_event_t *ev) { + int n; + char buf[1]; + ngx_err_t err; ngx_connection_t *c; ngx_http_request_t *r; ngx_http_proxy_ctx_t *p; @@ -376,15 +379,18 @@ void ngx_http_proxy_check_broken_connect ngx_log_debug1(NGX_LOG_DEBUG_HTTP, ev->log, 0, "http proxy check client, write event:%d", ev->write); - c = ev->data; - r = c->data; - p = ngx_http_get_module_ctx(r, ngx_http_proxy_module); - #if (HAVE_KQUEUE) - /* TODO: KEVENT_EVENT */ + if (ngx_event_flags & NGX_HAVE_KQUEUE_EVENT) { - if (ev->kq_eof) { + if (!ev->kq_eof) { + return; + } + + c = ev->data; + r = c->data; + p = ngx_http_get_module_ctx(r, ngx_http_proxy_module); + ev->eof = 1; if (ev->kq_errno) { @@ -407,17 +413,31 @@ void ngx_http_proxy_check_broken_connect if (p->upstream == NULL || p->upstream->peer.connection == NULL) { ngx_http_proxy_finalize_request(p, NGX_HTTP_CLIENT_CLOSED_REQUEST); } + + return; } -#else +#endif + + c = ev->data; + r = c->data; + p = ngx_http_get_module_ctx(r, ngx_http_proxy_module); n = recv(c->fd, buf, 1, MSG_PEEK); if (n > 0) { - /* TODO: delete level */ + if ((ngx_event_flags & NGX_USE_LEVEL_EVENT) && ev->active) { + if (ngx_del_event(ev, NGX_READ_EVENT, 0) == NGX_ERROR) { + ngx_http_proxy_finalize_request(p, + NGX_HTTP_INTERNAL_SERVER_ERROR); + } + } + return; } + ev->eof = 1; + if (n == -1) { err = ngx_socket_errno; if (err == NGX_EAGAIN) { @@ -426,9 +446,9 @@ void ngx_http_proxy_check_broken_connect ev->error = 1; - } else if (n == 0) { + } else { + /* n == 0 */ err = 0; - ev->eof = 1; } if (!p->cachable && p->upstream->peer.connection) { @@ -439,14 +459,12 @@ void ngx_http_proxy_check_broken_connect return; } - ngx_log_error(NGX_LOG_INFO, ev->log, ev->err, + ngx_log_error(NGX_LOG_INFO, ev->log, err, "client have closed prematurely connection"); if (p->upstream == NULL || p->upstream->peer.connection == NULL) { ngx_http_proxy_finalize_request(p, NGX_HTTP_CLIENT_CLOSED_REQUEST); } - -#endif } @@ -870,8 +888,15 @@ static char *ngx_http_proxy_merge_loc_co ngx_conf_merge_size_value(conf->header_buffer_size, prev->header_buffer_size, 4096); + ngx_conf_merge_bufs_value(conf->bufs, prev->bufs, 8, 4096); + if (conf->bufs.num < 2) { + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, + "there must be at least 2 \"proxy_buffers\""); + return NGX_CONF_ERROR; + } + size = conf->header_buffer_size; if (size < conf->bufs.size) { size = conf->bufs.size; @@ -891,6 +916,14 @@ static char *ngx_http_proxy_merge_loc_co "one of the \"proxy_buffers\""); return NGX_CONF_ERROR; + + } else if (conf->busy_buffers_size > (conf->bufs.num - 1) * conf->bufs.size) + { + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, + "\"proxy_busy_buffers_size\" must be less than " + "the size of all \"proxy_buffers\" minus one buffer"); + + return NGX_CONF_ERROR; } diff --git a/src/os/unix/ngx_process.c b/src/os/unix/ngx_process.c --- a/src/os/unix/ngx_process.c +++ b/src/os/unix/ngx_process.c @@ -1,6 +1,7 @@ #include #include +#include static void ngx_execute_proc(ngx_cycle_t *cycle, void *data); @@ -142,6 +143,18 @@ void ngx_process_get_status() return; } + + if (ngx_accept_mutex_ptr) { + + /* + * unlock the accept mutex if the abnormally exited process + * held it + */ + + ngx_atomic_cmp_set(ngx_accept_mutex_ptr, pid, 0); + } + + one = 1; process = ""; diff --git a/src/os/win32/ngx_process_cycle.c b/src/os/win32/ngx_process_cycle.c --- a/src/os/win32/ngx_process_cycle.c +++ b/src/os/win32/ngx_process_cycle.c @@ -16,6 +16,8 @@ sig_atomic_t ngx_timer; #endif +ngx_int_t ngx_threaded; + sig_atomic_t ngx_terminate; sig_atomic_t ngx_quit;