diff options
author | Igor Sysoev <igor@sysoev.ru> | 2003-05-12 19:52:24 +0400 |
---|---|---|
committer | Igor Sysoev <igor@sysoev.ru> | 2003-05-12 19:52:24 +0400 |
commit | 6b863e353d54420c323d67f86aad0b90ba04e316 (patch) | |
tree | 51d13ab529d2605be3995333d71344c917c5c4f4 /src/event | |
parent | 4fe262b6821a461b3dbb3d6bfd05a8f713157524 (diff) |
nginx-0.0.1-2003-05-12-19:52:24 import
Diffstat (limited to 'src/event')
-rw-r--r-- | src/event/modules/ngx_kqueue_module.c | 42 | ||||
-rw-r--r-- | src/event/ngx_event.h | 5 | ||||
-rw-r--r-- | src/event/ngx_event_accept.c | 6 | ||||
-rw-r--r-- | src/event/ngx_event_connect.c | 126 | ||||
-rw-r--r-- | src/event/ngx_event_connect.h | 43 | ||||
-rw-r--r-- | src/event/ngx_event_timer.c | 7 |
6 files changed, 192 insertions, 37 deletions
diff --git a/src/event/modules/ngx_kqueue_module.c b/src/event/modules/ngx_kqueue_module.c index 4fe9e6b53..0c2ce35bf 100644 --- a/src/event/modules/ngx_kqueue_module.c +++ b/src/event/modules/ngx_kqueue_module.c @@ -141,7 +141,7 @@ int ngx_kqueue_del_event(ngx_event_t *ev, int event, u_int flags) if (nchanges > 0 && ev->index < nchanges - && change_list[ev->index].udata == ev) + && (void *) ((uintptr_t) change_list[ev->index].udata & ~1) == ev) { #if (NGX_DEBUG_EVENT) ngx_connection_t *c = (ngx_connection_t *) ev->data; @@ -159,8 +159,9 @@ int ngx_kqueue_del_event(ngx_event_t *ev, int event, u_int flags) return NGX_OK; } - /* when a socket is closed kqueue automatically deletes its filters - so we do not need to delete a event explicity before a socket closing */ + /* when the file descriptor is closed a kqueue automatically deletes + its filters so we do not need to delete explicity the event + before the closing the file descriptor */ if (flags & NGX_CLOSE_EVENT) { return NGX_OK; @@ -200,7 +201,7 @@ int ngx_kqueue_set_event(ngx_event_t *ev, int filter, u_int flags) change_list[nchanges].ident = c->fd; change_list[nchanges].filter = filter; change_list[nchanges].flags = flags; - change_list[nchanges].udata = ev; + change_list[nchanges].udata = (void *) ((uintptr_t) ev | ev->instance); #if (HAVE_LOWAT_EVENT) @@ -230,7 +231,7 @@ int ngx_kqueue_set_event(ngx_event_t *ev, int filter, u_int flags) int ngx_kqueue_process_events(ngx_log_t *log) { - int events, i; + int events, instance, i; ngx_msec_t timer, delta; ngx_event_t *ev; struct timeval tv; @@ -310,12 +311,15 @@ int ngx_kqueue_process_events(ngx_log_t *log) } ev = (ngx_event_t *) event_list[i].udata; + instance = (uintptr_t) ev & 1; + ev = (void *) ((uintptr_t) ev & ~1); - /* It's a stale event from a socket + /* It's a stale event from a file descriptor that was just closed in this iteration */ - if (!ev->active) { - continue; + if (ev->active == 0 || ev->instance != instance) { + ngx_log_debug(log, "stale kevent"); + continue; } switch (event_list[i].filter) { @@ -323,28 +327,6 @@ int ngx_kqueue_process_events(ngx_log_t *log) case EVFILT_READ: case EVFILT_WRITE: - if (ev->first) { - if (nchanges > 0 - && ev->index < nchanges - && change_list[ev->index].udata == ev) { - - /* It's a stale event from a socket that was just closed - in this iteration and during processing another socket - was opened with the same number by accept() or socket() - and its event has been added the event to the change_list - but has not been passed to a kernel. Nevertheless - there's small chance that ngx_kqueue_set_event() has - flushed the new event if the change_list was filled up. - In this very rare case we would get EAGAIN while - a reading or a writing */ - - continue; - - } else { - ev->first = 0; - } - } - ev->available = event_list[i].data; if (event_list[i].flags & EV_EOF) { diff --git a/src/event/ngx_event.h b/src/event/ngx_event.h index c3cc9079e..bc8cae52e 100644 --- a/src/event/ngx_event.h +++ b/src/event/ngx_event.h @@ -63,7 +63,9 @@ struct ngx_event_s { #endif unsigned write:1; - unsigned first:1; + unsigned instance:1; /* used to detect stale events in kqueue, + rt signals and epoll */ + unsigned active:1; unsigned ready:1; unsigned timedout:1; @@ -114,6 +116,7 @@ struct ngx_event_s { #endif }; + typedef enum { NGX_SELECT_EVENT_N = 0, #if (HAVE_POLL) diff --git a/src/event/ngx_event_accept.c b/src/event/ngx_event_accept.c index aa2911c31..411f2b1ad 100644 --- a/src/event/ngx_event_accept.c +++ b/src/event/ngx_event_accept.c @@ -16,6 +16,7 @@ int ngx_event_accept(ngx_event_t *ev) { + int instance; socklen_t len; struct sockaddr *sa; ngx_err_t err; @@ -95,6 +96,8 @@ int ngx_event_accept(ngx_event_t *ev) wev = &ngx_write_events[s]; c = &ngx_connections[s]; + instance = rev->instance; + ngx_memzero(rev, sizeof(ngx_event_t)); ngx_memzero(wev, sizeof(ngx_event_t)); ngx_memzero(c, sizeof(ngx_connection_t)); @@ -108,6 +111,8 @@ int ngx_event_accept(ngx_event_t *ev) c->addr_text_max_len = ls->addr_text_max_len; c->post_accept_timeout = ls->post_accept_timeout; + rev->instance = wev->instance = !instance; + rev->index = wev->index = NGX_INVALID_INDEX; rev->data = wev->data = c; @@ -117,7 +122,6 @@ int ngx_event_accept(ngx_event_t *ev) c->fd = s; c->unexpected_eof = 1; wev->write = 1; - rev->first = wev->first = 1; #if (USE_KQUEUE) wev->ready = 1; diff --git a/src/event/ngx_event_connect.c b/src/event/ngx_event_connect.c new file mode 100644 index 000000000..ca8a4a3b3 --- /dev/null +++ b/src/event/ngx_event_connect.c @@ -0,0 +1,126 @@ + +#include <ngx_event_connect.h> + + +int ngx_event_connect_peer(ngx_connect_peer_t *cp) +{ + + + if (cp->peers->number > 1) { + + /* it's a first try - get current peer */ + + if (cp->tries == cp->peers->number) { + + /* Here is the race condition + when the peers are shared between + the threads or the processes but it should not be serious */ + + cp->cur_peer = cp->peers->current++; + + if (cp->peers->current >= cp->peers->number) { + cp->peers->current = 0; + } + + /* */ + +#if (NGX_MULTITHREADED || NGX_MULTIPROCESSED) + /* eliminate the sequences of the race condition */ + if (cp->cur_peer >= cp->peers->number) { + cp->cur_peer = 0; + } +#endif + } + + if (cp->peers->max_fails > 0) { + + for ( ;; ) { + peer = &cp->peers->peers[cp->cur_peer]; + + /* Here is the race condition + when the peers are shared between + the threads or the processes but it should not be serious */ + + if (peer->fails <= cp->peers->max_fails + || (now - peer->accessed > cp->peers->fail_timeout)) + { + break; + } + + /* */ + + cp->cur_peer++; + + if (cp->cur_peer >= cp->peers->number) { + cp->cur_peer = 0; + } + + cp->tries--; + + if (cp->tries == 0) { + return NGX_ERROR; + } + } + } + } + + + + + + s = ngx_socket(AF_INET, SOCK_STREAM, IPPROTO_IP, 0); + + if (s == -1) { + ngx_log_error(NGX_LOG_ALERT, cn->log, ngx_socket_errno, + ngx_socket_n " failed"); + return NGX_HTTP_INTERNAL_SERVER_ERROR; + } + + if (cn->rcvbuf) { + if (setsockopt(s, SOL_SOCKET, SO_RCVBUF, + (const void *) &cn->rcvbuf, sizeof(int)) == -1) { + ngx_log_error(NGX_LOG_ALERT, cn->log, ngx_socket_errno, + "setsockopt(SO_RCVBUF) failed"); + + if (ngx_close_socket(s) == -1) { + ngx_log_error(NGX_LOG_ALERT, cn->log, ngx_socket_errno, + ngx_close_socket_n " failed"); + } + + return NGX_HTTP_INTERNAL_SERVER_ERROR; + } + } + + if (ngx_nonblocking(s) == -1) { + ngx_log_error(NGX_LOG_ALERT, cn->log, ngx_socket_errno, + ngx_nonblocking_n " failed"); + + if (ngx_close_socket(s) == -1) { + ngx_log_error(NGX_LOG_ALERT, cn->log, ngx_socket_errno, + ngx_close_socket_n " failed"); + } + + return NGX_HTTP_INTERNAL_SERVER_ERROR; + } + + c = &ngx_connections[s]; + rev = &ngx_read_events[s]; + wev = &ngx_write_events[s]; + + instance = rev->instance; + + ngx_memzero(c, sizeof(ngx_connection_t)); + ngx_memzero(rev, sizeof(ngx_event_t)); + ngx_memzero(wev, sizeof(ngx_event_t)); + + rev->index = wev->index = NGX_INVALID_INDEX; + rev->data = wev->data = c; + c->read = rev; + c->write = wev; + + rev->instance = wev->instance = !instance; + + rev->log = wev->log = c->log = cn->log; + c->fd = s; + wev->close_handler = rev->close_handler = ngx_event_close_connection; + diff --git a/src/event/ngx_event_connect.h b/src/event/ngx_event_connect.h new file mode 100644 index 000000000..ecfedf993 --- /dev/null +++ b/src/event/ngx_event_connect.h @@ -0,0 +1,43 @@ +#ifndef _NGX_EVENT_CONNECT_H_INCLUDED_ +#define _NGX_EVENT_CONNECT_H_INCLUDED_ + + +#include <ngx_config.h> +#include <ngx_string.h> +#include <ngx_log.h> +#include <ngx_event.h> +#include <ngx_connection.h> + + +typedef struct { + u_int32_t addr; + ngx_str_t host; + int port; + ngx_str_t addr_port_name; + + int fails; + time_t accessed; +} ngx_peer_t; + + +typedef struct { + int current; + int number; + int max_fails; + int fail_timeout; + + /* ngx_mutex_t *mutex; */ + /* ngx_connection_t *cached; */ + + ngx_peer_t peers[1]; +} ngx_peers_t; + + +typedef struct { + ngx_peers_t *peers; + int cur_peer; + int tries; +} ngx_connect_peer_t; + + +#endif /* _NGX_EVENT_CONNECT_H_INCLUDED_ */ diff --git a/src/event/ngx_event_timer.c b/src/event/ngx_event_timer.c index aebbaf839..f32ce470c 100644 --- a/src/event/ngx_event_timer.c +++ b/src/event/ngx_event_timer.c @@ -45,7 +45,8 @@ void ngx_event_add_timer(ngx_event_t *ev, ngx_msec_t timer) #if (NGX_DEBUG_EVENT) ngx_connection_t *c = (ngx_connection_t *) ev->data; - ngx_log_debug(ev->log, "set timer: %d:%d" _ c->fd _ timer); + ngx_log_debug(ev->log, "set timer: %d:%d, slot: %d" _ + c->fd _ timer _ ngx_timer_cur_queue); #endif if (ev->timer_next || ev->timer_prev) { @@ -53,10 +54,6 @@ void ngx_event_add_timer(ngx_event_t *ev, ngx_msec_t timer) return; } -#if (NGX_DEBUG_EVENT) - ngx_log_debug(ev->log, "timer slot: %d" _ ngx_timer_cur_queue); -#endif - for (e = ngx_timer_queue[ngx_timer_cur_queue].timer_next; e != &ngx_timer_queue[ngx_timer_cur_queue] && timer > e->timer_delta; e = e->timer_next) |