summaryrefslogtreecommitdiffhomepage
path: root/src/event
diff options
context:
space:
mode:
authorIgor Sysoev <igor@sysoev.ru>2003-03-20 16:09:44 +0000
committerIgor Sysoev <igor@sysoev.ru>2003-03-20 16:09:44 +0000
commitdc479b4d98d5b65b78689c5282a31c70efadd928 (patch)
tree7caf32d89eec03484b14ebe74dfefd2a80c8fa02 /src/event
parent90ace68b69606b885578686e19d499a50d5e80b7 (diff)
downloadnginx-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.c5
-rw-r--r--src/event/modules/ngx_iocp_module.c6
-rw-r--r--src/event/modules/ngx_kqueue_module.c53
-rw-r--r--src/event/modules/ngx_poll_module.c5
-rw-r--r--src/event/modules/ngx_select_module.c5
-rw-r--r--src/event/ngx_event.h19
-rw-r--r--src/event/ngx_event_accept.c1
-rw-r--r--src/event/ngx_event_acceptex.c1
-rw-r--r--src/event/ngx_event_recv.c130
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
}