diff options
| author | Igor Sysoev <igor@sysoev.ru> | 2003-03-20 16:09:44 +0000 |
|---|---|---|
| committer | Igor Sysoev <igor@sysoev.ru> | 2003-03-20 16:09:44 +0000 |
| commit | dc479b4d98d5b65b78689c5282a31c70efadd928 (patch) | |
| tree | 7caf32d89eec03484b14ebe74dfefd2a80c8fa02 /src/event | |
| parent | 90ace68b69606b885578686e19d499a50d5e80b7 (diff) | |
| download | nginx-dc479b4d98d5b65b78689c5282a31c70efadd928.tar.gz nginx-dc479b4d98d5b65b78689c5282a31c70efadd928.tar.bz2 | |
nginx-0.0.1-2003-03-20-19:09:44 import
Diffstat (limited to 'src/event')
| -rw-r--r-- | src/event/modules/ngx_devpoll_module.c | 5 | ||||
| -rw-r--r-- | src/event/modules/ngx_iocp_module.c | 6 | ||||
| -rw-r--r-- | src/event/modules/ngx_kqueue_module.c | 53 | ||||
| -rw-r--r-- | src/event/modules/ngx_poll_module.c | 5 | ||||
| -rw-r--r-- | src/event/modules/ngx_select_module.c | 5 | ||||
| -rw-r--r-- | src/event/ngx_event.h | 19 | ||||
| -rw-r--r-- | src/event/ngx_event_accept.c | 1 | ||||
| -rw-r--r-- | src/event/ngx_event_acceptex.c | 1 | ||||
| -rw-r--r-- | src/event/ngx_event_recv.c | 130 |
9 files changed, 158 insertions, 67 deletions
diff --git a/src/event/modules/ngx_devpoll_module.c b/src/event/modules/ngx_devpoll_module.c index e2e7750f1..fbbcf5992 100644 --- a/src/event/modules/ngx_devpoll_module.c +++ b/src/event/modules/ngx_devpoll_module.c @@ -236,6 +236,7 @@ int ngx_devpoll_process_events(ngx_log_t *log) if ((int) timer != INFTIM) { gettimeofday(&tv, NULL); delta = tv.tv_sec * 1000 + tv.tv_usec / 1000 - delta; + ngx_event_expire_timers(delta); } else { if (events == 0) { @@ -305,9 +306,5 @@ int ngx_devpoll_process_events(ngx_log_t *log) } } - if ((int) timer != INFTIM) { - ngx_event_expire_timers(delta); - } - return NGX_OK; } diff --git a/src/event/modules/ngx_iocp_module.c b/src/event/modules/ngx_iocp_module.c index f474c4c61..a84daa8e5 100644 --- a/src/event/modules/ngx_iocp_module.c +++ b/src/event/modules/ngx_iocp_module.c @@ -110,6 +110,7 @@ int ngx_iocp_process_events(ngx_log_t *log) if (timer != INFINITE) { delta = ngx_msec() - delta; + ngx_event_expire_timers(delta); } if (ovlp) { @@ -118,6 +119,7 @@ int ngx_iocp_process_events(ngx_log_t *log) ngx_log_debug(log, "iocp ev: %08x" _ ev); if (ev == e) { + /* it's not AcceptEx() completion */ ev->ready = 1; ev->available = bytes; } @@ -129,9 +131,5 @@ ngx_log_debug(log, "iocp ev: %08x" _ ev->event_handler); } } - if (timer != INFINITE) { - ngx_event_expire_timers(delta); - } - return NGX_OK; } diff --git a/src/event/modules/ngx_kqueue_module.c b/src/event/modules/ngx_kqueue_module.c index b49eb62bb..bc2fe217e 100644 --- a/src/event/modules/ngx_kqueue_module.c +++ b/src/event/modules/ngx_kqueue_module.c @@ -110,6 +110,13 @@ int ngx_kqueue_add_event(ngx_event_t *ev, int event, u_int flags) ev->active = 1; ev->oneshot = (flags & NGX_ONESHOT_EVENT) ? 1: 0; + /* The event addition or change should be always passed to a kernel + because there can be case when event was passed to a kernel then + added again to the change_list and then deleted from the change_list + by ngx_kqueue_del_event() so the first event still remains in a kernel */ + +#if 0 + if (nchanges > 0 && ev->index < nchanges && change_list[ev->index].udata == ev) @@ -118,12 +125,17 @@ int ngx_kqueue_add_event(ngx_event_t *ev, int event, u_int flags) ngx_connection_t *c = (ngx_connection_t *) ev->data; ngx_log_debug(ev->log, "kqueue add event: %d: ft:%d" _ c->fd _ event); #endif + + /* if the event is still not passed to a kernel we change it */ + change_list[ev->index].filter = event; change_list[ev->index].flags = flags; return NGX_OK; } +#endif + return ngx_kqueue_set_event(ev, event, EV_ADD | flags); } @@ -142,6 +154,9 @@ int ngx_kqueue_del_event(ngx_event_t *ev, int event, u_int flags) ngx_connection_t *c = (ngx_connection_t *) ev->data; ngx_log_debug(ev->log, "kqueue del event: %d: ft:%d" _ c->fd _ event); #endif + + /* if the event is still not passed to a kernel we will not pass it */ + if (ev->index < --nchanges) { e = (ngx_event_t *) change_list[nchanges].udata; change_list[ev->index] = change_list[nchanges]; @@ -151,6 +166,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 */ + if (flags & NGX_CLOSE_EVENT) { return NGX_OK; } @@ -257,6 +275,11 @@ int ngx_kqueue_process_events(ngx_log_t *log) gettimeofday(&tv, NULL); delta = tv.tv_sec * 1000 + tv.tv_usec / 1000 - delta; + /* Expired timers must be deleted before the events processing + because the new timers can be added during the processing */ + + ngx_event_expire_timers(delta); + } else { if (events == 0) { ngx_log_error(NGX_LOG_ALERT, log, 0, @@ -295,6 +318,9 @@ int ngx_kqueue_process_events(ngx_log_t *log) ev = (ngx_event_t *) event_list[i].udata; + /* It's a stale event from a socket + that was just closed in this iteration */ + if (!ev->active) { continue; } @@ -303,6 +329,29 @@ 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) { @@ -332,9 +381,5 @@ int ngx_kqueue_process_events(ngx_log_t *log) } } - if (timer) { - ngx_event_expire_timers(delta); - } - return NGX_OK; } diff --git a/src/event/modules/ngx_poll_module.c b/src/event/modules/ngx_poll_module.c index 25319c806..23bcc3f33 100644 --- a/src/event/modules/ngx_poll_module.c +++ b/src/event/modules/ngx_poll_module.c @@ -175,6 +175,7 @@ int ngx_poll_process_events(ngx_log_t *log) if ((int) timer != INFTIM) { delta = ngx_msec() - delta; + ngx_event_expire_timers(delta); } else { if (ready == 0) { @@ -259,9 +260,5 @@ int ngx_poll_process_events(ngx_log_t *log) ngx_log_error(NGX_LOG_ALERT, log, 0, "poll ready != events"); } - if ((int) timer != INFTIM) { - ngx_event_expire_timers(delta); - } - return NGX_OK; } diff --git a/src/event/modules/ngx_select_module.c b/src/event/modules/ngx_select_module.c index 50d030c74..e7abfaa6c 100644 --- a/src/event/modules/ngx_select_module.c +++ b/src/event/modules/ngx_select_module.c @@ -243,6 +243,7 @@ int ngx_select_process_events(ngx_log_t *log) if (timer) { delta = ngx_msec() - delta; + ngx_event_expire_timers(delta); } else { if (ready == 0) { @@ -312,9 +313,5 @@ int ngx_select_process_events(ngx_log_t *log) ngx_log_error(NGX_LOG_ALERT, log, 0, "select ready != events"); } - if (timer) { - ngx_event_expire_timers(delta); - } - return NGX_OK; } diff --git a/src/event/ngx_event.h b/src/event/ngx_event.h index c36306db7..4c553c001 100644 --- a/src/event/ngx_event.h +++ b/src/event/ngx_event.h @@ -63,6 +63,7 @@ struct ngx_event_s { #endif unsigned write:1; + unsigned first:1; unsigned active:1; unsigned ready:1; unsigned timedout:1; @@ -179,8 +180,8 @@ typedef struct { #define NGX_USE_LEVEL_EVENT 0x00010000 -/* Event filter is deleted before closing file. Has no meaning - for select, poll, epoll. +/* Event filter is deleted before 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 @@ -193,16 +194,24 @@ typedef struct { #define NGX_READ_EVENT EVFILT_READ #define NGX_WRITE_EVENT EVFILT_WRITE +#define NGX_ENABLE_EVENT EV_ENABLE +#define NGX_DISABLE_EVENT EV_DISABLE + +/* NGX_CLOSE_EVENT is the module flag and it would not go into a kernel + so we need to choose the value that would not interfere with any existent + and future flags. kqueue has such values - EV_FLAG1, EV_EOF and EV_ERROR. + They are reserved and cleared on a kernel entrance */ +#undef NGX_CLOSE_EVENT +#define NGX_CLOSE_EVENT EV_FLAG1 + #define NGX_LEVEL_EVENT 0 #define NGX_ONESHOT_EVENT EV_ONESHOT +#define NGX_CLEAR_EVENT EV_CLEAR #ifndef HAVE_CLEAR_EVENT #define HAVE_CLEAR_EVENT 1 #endif -#if (HAVE_CLEAR_EVENT) -#define NGX_CLEAR_EVENT EV_CLEAR -#endif #elif (HAVE_POLL) || (HAVE_DEVPOLL) diff --git a/src/event/ngx_event_accept.c b/src/event/ngx_event_accept.c index 3bb141e2f..56e90a3f9 100644 --- a/src/event/ngx_event_accept.c +++ b/src/event/ngx_event_accept.c @@ -117,6 +117,7 @@ int ngx_event_accept(ngx_event_t *ev) c->fd = s; c->unexpected_eof = 1; wev->write = 1; + rev->first = wev->first = 1; #if (HAVE_AIO_EVENT) if (!(ngx_event_flags & NGX_HAVE_AIO_EVENT)) { diff --git a/src/event/ngx_event_acceptex.c b/src/event/ngx_event_acceptex.c index 0654c80fa..07d999388 100644 --- a/src/event/ngx_event_acceptex.c +++ b/src/event/ngx_event_acceptex.c @@ -104,6 +104,7 @@ int ngx_event_post_acceptex(ngx_listen_t *ls, int n) c->unexpected_eof = 1; wev->write = 1; + rev->first = wev->first = 1; c->handler = ls->handler; rev->event_handler = ngx_event_acceptex; diff --git a/src/event/ngx_event_recv.c b/src/event/ngx_event_recv.c index 46c165af1..c083e8f61 100644 --- a/src/event/ngx_event_recv.c +++ b/src/event/ngx_event_recv.c @@ -8,18 +8,13 @@ ssize_t ngx_event_recv_core(ngx_connection_t *c, char *buf, size_t size) { - int n; - ngx_err_t err; - ngx_event_t *ev; + ssize_t n; + ngx_err_t err; + ngx_event_t *ev; ev = c->read; - if (ev->timedout) { - ngx_set_socket_errno(NGX_ETIMEDOUT); - ngx_log_error(NGX_LOG_ERR, c->log, NGX_ETIMEDOUT, "recv() failed"); - return NGX_ERROR; - } - +/* DEBUG */ #if (HAVE_KQUEUE) if (ngx_event_flags & NGX_HAVE_KQUEUE_EVENT) { ngx_log_debug(c->log, "ngx_event_recv: eof:%d, avail:%d, err:%d" _ @@ -30,54 +25,77 @@ ssize_t ngx_event_recv_core(ngx_connection_t *c, char *buf, size_t size) #if (USE_KQUEUE) if (ev->eof && ev->available == 0) { - if (ev->error) { - ngx_set_socket_errno(ev->error); - if (ev->error == NGX_ECONNRESET && ev->ignore_econnreset) { - return 0; - } + if (ev->error == 0) { + return 0; + } + + ngx_set_socket_errno(ev->error); + err = ev->error; + n = -1; + + } else { + n = ngx_recv(c->fd, buf, size, 0); + + if (n == -1) { + err = ngx_socket_errno; + } + } + + if (n == -1) { + ev->ready = 0; - ngx_log_error(NGX_LOG_ERR, c->log, ev->error, - "recv() failed"); - return NGX_ERROR; + if (err == NGX_ECONNRESET && ev->ignore_econnreset) { + return 0; } - return 0; + if (err == NGX_EAGAIN) { + ngx_log_error(NGX_LOG_INFO, c->log, err, "recv() returned EAGAIN"); + return NGX_AGAIN; + } + + ngx_log_error(NGX_LOG_ERR, c->log, err, "recv() failed"); + return NGX_ERROR; } -#elif (HAVE_KQUEUE) + ev->available -= n; + if (ev->available == 0) { + ev->ready = 0; + } - if (ngx_event_flags & NGX_HAVE_KQUEUE_EVENT) { - if (ev->eof && ev->available == 0) { - if (ev->error) { - ngx_set_socket_errno(ev->error); + return n; - if (ev->error == NGX_ECONNRESET && ev->ignore_econnreset) { - return 0; - } +#elif (HAVE_KQUEUE) - ngx_log_error(NGX_LOG_ERR, c->log, ev->error, - "recv() failed"); - return NGX_ERROR; - } + if ((ngx_event_flags & NGX_HAVE_KQUEUE_EVENT) + && ev->eof && ev->available == 0) { + if (ev->error == 0) { return 0; } - } -#endif + ngx_set_socket_errno(ev->error); + err = ev->error; + n = -1; - n = ngx_recv(c->fd, buf, size, 0); + } else { + n = ngx_recv(c->fd, buf, size, 0); +ngx_log_debug(c->log, "ngx_event_recv: read:%d:%d" _ n _ size); + + if (n == -1) { + err = ngx_socket_errno; + } + } if (n == -1) { - err = ngx_socket_errno; + ev->ready = 0; - if (ev->error == NGX_ECONNRESET && ev->ignore_econnreset) { + if (err == NGX_ECONNRESET && ev->ignore_econnreset) { return 0; } if (err == NGX_EAGAIN) { - ngx_log_error(NGX_LOG_INFO, c->log, err, "recv() returns EAGAIN"); + ngx_log_error(NGX_LOG_INFO, c->log, err, "recv() returned EAGAIN"); return NGX_AGAIN; } @@ -85,17 +103,45 @@ ssize_t ngx_event_recv_core(ngx_connection_t *c, char *buf, size_t size) return NGX_ERROR; } -#if (USE_KQUEUE) + if (ngx_event_flags & NGX_HAVE_KQUEUE_EVENT) { + ev->available -= n; + if (ev->available == 0) { + ev->ready = 0; + } - ev->available -= n; + } else if ((size_t) n < size) { + ev->ready = 0; + } -#elif (HAVE_KQUEUE) + return n; - if (ngx_event_flags & NGX_HAVE_KQUEUE_EVENT) { - ev->available -= n; +#else /* not kqueue */ + + n = ngx_recv(c->fd, buf, size, 0); + + if (n == -1) { + err = ngx_socket_errno; + + ev->ready = 0; + + if (err == NGX_ECONNRESET && ev->ignore_econnreset) { + return 0; + } + + if (err == NGX_EAGAIN) { + ngx_log_error(NGX_LOG_INFO, c->log, err, "recv() returned EAGAIN"); + return NGX_AGAIN; + } + + ngx_log_error(NGX_LOG_ERR, c->log, err, "recv() failed"); + return NGX_ERROR; } -#endif + if ((size_t) n < size) { + ev->ready = 0; + } return n; + +#endif } |
