}
ev->active = 0;
- ev->posted = 0;
if (flags & NGX_CLOSE_EVENT) {
return NGX_OK;
if (flags & NGX_CLOSE_EVENT) {
ev->active = 0;
- ev->posted = 0;
return NGX_OK;
}
}
ev->active = 0;
- ev->posted = 0;
return NGX_OK;
}
ev->active = 0;
ev->disabled = 0;
- if (ngx_mutex_lock(ngx_posted_events_mutex) == NGX_ERROR) {
- return NGX_ERROR;
- }
- ev->posted = 0;
- ngx_mutex_unlock(ngx_posted_events_mutex);
-
if (ngx_thread_main()
&& nchanges > 0
&& ev->index < (u_int) nchanges
instance = (uintptr_t) ev & 1;
ev = (ngx_event_t *) ((uintptr_t) ev & (uintptr_t) ~1);
- if (!ev->active || ev->instance != instance) {
+ if (ev->closed || ev->instance != instance) {
/*
* the stale event from a file descriptor
ev->returned_instance = instance;
- if (!ev->accept && (ngx_threaded || ngx_accept_mutex_held)) {
+#if (NGX_THREADS)
+
+ if (ngx_threaded && !ev->accept) {
ev->posted_ready = 1;
ev->posted_available += event_list[i].data;
continue;
}
+#endif
+
ev->available = event_list[i].data;
if (event_list[i].flags & EV_EOF) {
- ev->kq_eof = 1;
+ ev->pending_eof = 1;
ev->kq_errno = event_list[i].fflags;
}
continue;
}
-#if 0
if (!ev->accept) {
ngx_post_event(ev);
continue;
}
-#endif
if (ngx_accept_disabled > 0) {
continue;
c = ev->data;
ev->active = 0;
- ev->posted = 0;
if (ev->index == NGX_INVALID_INDEX) {
ngx_log_error(NGX_LOG_ALERT, ev->log, 0,
if (flags & NGX_CLOSE_EVENT) {
c->read->active = 0;
c->write->active = 0;
- c->read->posted = 0;
- c->write->posted = 0;
return NGX_OK;
}
c->read->active = 0;
c->write->active = 0;
- c->read->posted = 0;
- c->write->posted = 0;
return NGX_OK;
}
c = ev->data;
ev->active = 0;
- ev->posted = 0;
if (ev->index == NGX_INVALID_INDEX) {
return NGX_OK;
return NGX_ERROR;
}
+ rev = cycle->read_events;
+ for (i = 0; i < cycle->connection_n; i++) {
+ rev[i].closed = 1;
+ }
+
cycle->write_events = ngx_alloc(sizeof(ngx_event_t) * ecf->connections,
cycle->log);
if (cycle->write_events == NULL) {
return NGX_ERROR;
}
+ wev = cycle->write_events;
+ for (i = 0; i < cycle->connection_n; i++) {
+ wev[i].closed = 1;
+ }
+
/* for each listening socket */
s = cycle->listening.elts;
struct ngx_event_s {
void *data;
- /* TODO rename to handler */
- ngx_event_handler_pt event_handler;
-
- u_int index;
-
- /* the link of the posted queue or the event mutecies queues */
- ngx_event_t *next;
+ unsigned write:1;
- ngx_log_t *log;
+ unsigned accept:1;
- /*
- * The inline of "ngx_rbtree_t rbtree;".
- *
- * It allows to pack the rbtree_color and the various event bit flags into
- * the single "int". We also use "unsigned char" and then "unsigned short"
- * because otherwise MSVC 6.0 uses an additional "int" for the bit flags.
- * We use "char rbtree_color" instead of "unsigned int rbtree_color:1"
- * because it preserves the bits order on the big endian platforms.
- */
-
- ngx_int_t rbtree_key;
- void *rbtree_left;
- void *rbtree_right;
- void *rbtree_parent;
- char rbtree_color;
-
- unsigned char oneshot:1;
-
- unsigned char write:1;
+ unsigned oneshot: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;
+ unsigned use_instance:1;
+ unsigned instance:1;
+ unsigned returned_instance:1;
/*
* the event was passed or would be passed to a kernel;
* in aio mode - operation was posted.
*/
- unsigned char active:1;
+ unsigned active:1;
- unsigned char disabled:1;
-
- unsigned char posted:1;
+ unsigned disabled:1;
/* the ready event; in aio mode 0 means that no operation can be posted */
- unsigned short ready:1;
+ unsigned ready:1;
/* aio operation is complete */
- unsigned short complete:1;
-
- unsigned short eof:1;
- unsigned short error:1;
-
- unsigned short timedout:1;
- unsigned short timer_set:1;
+ unsigned complete:1;
- unsigned short delayed:1;
+ unsigned eof:1;
+ unsigned error:1;
- unsigned short read_discarded:1;
+ unsigned timedout:1;
+ unsigned timer_set:1;
- unsigned short unexpected_eof:1;
+ unsigned delayed:1;
- unsigned short accept:1;
+ unsigned read_discarded:1;
- unsigned short deferred_accept:1;
+ unsigned unexpected_eof:1;
- unsigned short overflow:1;
+ unsigned deferred_accept:1;
- /* TODO: aio_eof and kq_eof can be the single pending_eof */
- /* the pending eof in aio chain operation */
- unsigned short aio_eof:1;
+ unsigned overflow:1;
- /* the pending eof reported by kqueue */
- unsigned short kq_eof:1;
+ /* the pending eof reported by kqueue or in aio chain operation */
+ unsigned pending_eof:1;
#if (WIN32)
/* setsockopt(SO_UPDATE_ACCEPT_CONTEXT) was succesfull */
- unsigned short accept_context_updated:1;
+ unsigned accept_context_updated:1;
#endif
#if (HAVE_KQUEUE)
- unsigned short kq_vnode:1;
+ unsigned kq_vnode:1;
/* the pending errno reported by kqueue */
int kq_errno;
#if (HAVE_KQUEUE) || (HAVE_IOCP)
int available;
#else
- unsigned short available:1;
+ unsigned available:1;
#endif
+ /* TODO rename to handler */
+ ngx_event_handler_pt event_handler;
+
#if (HAVE_AIO)
#endif
+ u_int index;
-#if (NGX_THREADS)
+ ngx_log_t *log;
- ngx_atomic_t *lock;
+ /* TODO: threads: padding to cache line */
+
+ /*
+ * STUB: The inline of "ngx_rbtree_t rbtree;"
+ */
+
+ ngx_int_t rbtree_key;
+ void *rbtree_left;
+ void *rbtree_right;
+ void *rbtree_parent;
+ char rbtree_color;
+
+
+ unsigned closed:1;
+
+#if (NGX_THREADS)
unsigned locked:1;
unsigned posted_available:1;
#endif
+ ngx_atomic_t *lock;
+
#endif
+ /* the links of the posted queue */
+ ngx_event_t *next;
+ ngx_event_t **prev;
+
#if 0
*/
if (p->upstream->read->available == 0
- && (p->upstream->read->kq_eof || p->upstream->read->aio_eof))
+ && p->upstream->read->pending_eof)
{
p->upstream->read->ready = 0;
p->upstream->read->eof = 0;
return;
}
- ngx_posted_events = ev->next;
+ ngx_delete_posted_event(ev);
+
+#if 0
+ /* do not check instance ??? */
if (ev->accept) {
continue;
}
+#endif
- if ((!ev->posted && !ev->active)
+ if (ev->closed
|| (ev->use_instance && ev->instance != ev->returned_instance))
{
/*
continue;
}
- if (ev->posted) {
- ev->posted = 0;
- }
-
ev->event_handler(ev);
}
}
ngx_int_t ngx_event_thread_process_posted(ngx_cycle_t *cycle)
{
- ngx_event_t *ev, **ep;
+ ngx_event_t *ev;
for ( ;; ) {
ev = (ngx_event_t *) ngx_posted_events;
- ep = (ngx_event_t **) &ngx_posted_events;
for ( ;; ) {
return NGX_OK;
}
- ngx_log_debug2(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
- "posted event lock:%d " PTR_FMT,
- *(ev->lock), ev->lock);
-
if (ngx_trylock(ev->lock) == 0) {
ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
"posted event " PTR_FMT " is busy", ev);
- ep = &ev->next;
ev = ev->next;
continue;
}
- *ep = ev->next;
+ ngx_delete_posted_event(ev);
- if ((!ev->posted && !ev->active)
+ ngx_log_debug3(NGX_LOG_DEBUG_EVENT, cycle->log, 0,
+ "event instance: c:%d i:%d r:%d",
+ ev->closed, ev->instance, ev->returned_instance);
+
+ if (ev->closed
|| (ev->use_instance && ev->instance != ev->returned_instance))
{
/*
*/
ngx_log_debug1(NGX_LOG_DEBUG_EVENT, ngx_cycle->log, 0,
- "kevent: stale event " PTR_FMT, ev);
+ "stale posted event " PTR_FMT, ev);
ngx_unlock(ev->lock);
ev->locked = 1;
- if (ev->posted) {
- ev->ready = ev->posted_ready;
- ev->timedout = ev->posted_timedout;
- ev->available = ev->posted_available;
- ev->kq_eof = ev->posted_eof;
+ ev->ready |= ev->posted_ready;
+ ev->timedout |= ev->posted_timedout;
+ ev->available |= ev->posted_available;
+ ev->pending_eof |= ev->posted_eof;
#if (HAVE_KQUEUE)
- ev->kq_errno = ev->posted_errno;
+ ev->kq_errno |= ev->posted_errno;
+#endif
+
+ ev->posted_ready = 0;
+ ev->posted_timedout = 0;
+ ev->posted_available = 0;
+ ev->posted_eof = 0;
+#if (HAVE_KQUEUE)
+ ev->posted_errno = 0;
#endif
- ev->posted = 0;
- }
ngx_mutex_unlock(ngx_posted_events_mutex);
#define ngx_post_event(ev) \
- if (!ev->posted) { \
+ if (ev->prev == NULL) { \
ev->next = (ngx_event_t *) ngx_posted_events; \
+ ev->prev = (ngx_event_t **) &ngx_posted_events; \
ngx_posted_events = ev; \
- ev->posted = 1; \
-\
- ngx_log_debug3(NGX_LOG_DEBUG_CORE, ngx_cycle->log, 0, \
- "POST: %08X %08X %08X", ngx_posted_events, \
- (ngx_posted_events ? ngx_posted_events->next: 0), \
- ((ngx_posted_events && ngx_posted_events->next) ? \
- ngx_posted_events->next->next: 0)); \
-\
-}
-
-/*
-\
-{ int i; ngx_event_t *e;\
- e = (ngx_event_t *) ngx_posted_events; \
-for (i = 0; e && i < 10; e = e->next, i++) { \
- ngx_log_debug2(NGX_LOG_DEBUG_CORE, ngx_cycle->log, 0, \
- "POST: %d %08X", i, e);\
-}} \
-\
-*/
+ ngx_log_debug1(NGX_LOG_DEBUG_CORE, ngx_cycle->log, 0, \
+ "post event " PTR_FMT, ev); \
+ }
+
+#define ngx_delete_posted_event(ev) \
+ *(ev->prev) = ev->next; \
+ if (ev->next) { \
+ ev->next->prev = ev->prev; \
+ } \
+ ev->prev = NULL;
+
void ngx_event_process_posted(ngx_cycle_t *cycle);
((char *) node - offsetof(ngx_event_t, rbtree_key));
#if (NGX_THREADS)
- if (ngx_trylock(ev->lock) == 0) {
+
+ if (ngx_threaded && ngx_trylock(ev->lock) == 0) {
+
+ /*
+ * We can not change the timer of the event that is been
+ * handling by another thread. And we can not easy walk
+ * the rbtree to find a next expired timer so we exit the loop.
+ * However it should be rare case when the event that is
+ * been handling has expired timer.
+ */
+
break;
}
#endif
ev->timer_set = 0;
+#if (NGX_THREADS)
if (ngx_threaded) {
if (ngx_mutex_lock(ngx_posted_events_mutex) == NGX_ERROR) {
return;
}
ev->posted_timedout = 1;
+ ev->returned_instance = ev->instance;
ngx_post_event(ev);
ngx_mutex_unlock(ngx_posted_events_mutex);
+
+ ngx_unlock(ev->lock);
+
continue;
}
+#endif
ev->timedout = 1;
if (ngx_event_flags & NGX_HAVE_KQUEUE_EVENT) {
- if (!ev->kq_eof) {
+ if (!ev->pending_eof) {
return;
}
ngx_del_conn(c, NGX_CLOSE_EVENT);
} else {
- if (c->read->active || c->read->posted) {
+ if (c->read->active || c->read->disabled) {
ngx_del_event(c->read, NGX_READ_EVENT, NGX_CLOSE_EVENT);
}
- if (c->write->active || c->read->posted) {
+ if (c->write->active || c->read->disabled) {
ngx_del_event(c->write, NGX_WRITE_EVENT, NGX_CLOSE_EVENT);
}
}
if ((ngx_event_flags & NGX_HAVE_KQUEUE_EVENT)
&& !p->request_sent
- && c->write->kq_eof)
+ && c->write->pending_eof)
{
ngx_log_error(NGX_LOG_ERR, c->log, c->write->kq_errno,
"connect() failed");
ngx_del_timer(r->connection->write);
}
- if (r->connection->read->kq_eof) {
+ if (r->connection->read->pending_eof) {
#if (NGX_KQUEUE)
ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log,
r->connection->read->kq_errno,
ngx_del_conn(c, NGX_CLOSE_EVENT);
} else {
- if (c->read->active || c->read->posted || c->read->disabled) {
+ if (c->read->active || c->read->disabled) {
ngx_del_event(c->read, NGX_READ_EVENT, NGX_CLOSE_EVENT);
}
- if (c->write->active || c->write->posted || c->write->disabled) {
+ if (c->write->active || c->write->disabled) {
ngx_del_event(c->write, NGX_WRITE_EVENT, NGX_CLOSE_EVENT);
}
}
* before we clean the connection
*/
- fd = c->fd;
- c->fd = (ngx_socket_t) -1;
- c->data = NULL;
- ngx_destroy_pool(c->pool);
-
#if (NGX_THREADS)
if (ngx_mutex_lock(ngx_posted_events_mutex) == NGX_OK) {
+
ngx_unlock(&c->lock);
c->read->locked = 0;
c->write->locked = 0;
+ c->read->closed = 1;
+ c->write->closed = 1;
+
+ if (c->read->prev) {
+ ngx_delete_posted_event(c->read);
+ }
+
+ if (c->write->prev) {
+ ngx_delete_posted_event(c->write);
+ }
+
ngx_mutex_unlock(ngx_posted_events_mutex);
}
- ngx_log_debug2(NGX_LOG_DEBUG_HTTP, ngx_cycle->log, 0,
- "connection lock: %d " PTR_FMT, c->lock, &c->lock);
+#else
+
+ c->read->closed = 1;
+ c->write->closed = 1;
+
+ if (c->read->prev) {
+ ngx_delete_posted_event(c->read);
+ }
+
+ if (c->write->prev) {
+ ngx_delete_posted_event(c->write);
+ }
#endif
+ fd = c->fd;
+ c->fd = (ngx_socket_t) -1;
+ c->data = NULL;
+
+ ngx_destroy_pool(c->pool);
+
if (ngx_close_socket(fd) == -1) {
/* we use ngx_cycle->log because c->log was in c->pool */
ssize_t total;
ngx_err_t err;
- if (c->read->aio_eof) {
+ if (c->read->pending_eof) {
c->read->ready = 0;
return 0;
}
}
if (n == 0) {
- c->read->aio_eof = 1;
+ c->read->pending_eof = 1;
if (total) {
c->read->eof = 0;
c->read->ready = 1;
op.sem_num = 0;
op.sem_op = -1;
- op.sem_flg = SEM_UNDO;
+ op.sem_flg = 0;
if (semop(m->semid, &op, 1) == -1) {
ngx_log_error(NGX_LOG_ALERT, m->log, ngx_errno,
op.sem_num = 0;
op.sem_op = 1;
- op.sem_flg = SEM_UNDO;
+ op.sem_flg = 0;
if (semop(m->semid, &op, 1) == -1) {
ngx_log_error(NGX_LOG_ALERT, m->log, ngx_errno,
op.sem_num = 0;
op.sem_op = -1;
- op.sem_flg = SEM_UNDO;
+ op.sem_flg = 0;
if (semop(cv->semid, &op, 1) == -1) {
ngx_log_error(NGX_LOG_ALERT, cv->log, ngx_errno,
op.sem_num = 0;
op.sem_op = 1;
- op.sem_flg = SEM_UNDO;
+ op.sem_flg = 0;
if (semop(cv->semid, &op, 1) == -1) {
ngx_log_error(NGX_LOG_ALERT, cv->log, ngx_errno,
#if (HAVE_KQUEUE)
- if ((ngx_event_flags & NGX_HAVE_KQUEUE_EVENT) && wev->kq_eof) {
+ if ((ngx_event_flags & NGX_HAVE_KQUEUE_EVENT) && wev->pending_eof) {
ngx_log_error(NGX_LOG_INFO, c->log, wev->kq_errno,
"kevent() reported about an closed connection");
sigset_t set;
struct timeval tv;
- sigfillset(&set);
- sigdelset(&set, SIGALRM);
- sigdelset(&set, ngx_signal_value(NGX_TERMINATE_SIGNAL));
- sigdelset(&set, ngx_signal_value(NGX_SHUTDOWN_SIGNAL));
+ sigemptyset(&set);
+ sigaddset(&set, ngx_signal_value(NGX_RECONFIGURE_SIGNAL));
+ sigaddset(&set, ngx_signal_value(NGX_REOPEN_SIGNAL));
+ sigaddset(&set, ngx_signal_value(NGX_CHANGEBIN_SIGNAL));
err = ngx_thread_sigmask(SIG_BLOCK, &set, NULL);
if (err) {
if (ngx_event_flags & NGX_HAVE_KQUEUE_EVENT) {
ngx_log_debug3(NGX_LOG_DEBUG_EVENT, c->log, 0,
"readv: eof:%d, avail:%d, err:%d",
- rev->kq_eof, rev->available, rev->kq_errno);
+ rev->pending_eof, rev->available, rev->kq_errno);
if (rev->available == 0) {
- if (rev->kq_eof) {
+ if (rev->pending_eof) {
rev->ready = 0;
rev->eof = 1;
*/
if (rev->available <= 0) {
- if (!rev->kq_eof) {
+ if (!rev->pending_eof) {
rev->ready = 0;
}
if (ngx_event_flags & NGX_HAVE_KQUEUE_EVENT) {
ngx_log_debug3(NGX_LOG_DEBUG_EVENT, c->log, 0,
"recv: eof:%d, avail:%d, err:%d",
- rev->kq_eof, rev->available, rev->kq_errno);
+ rev->pending_eof, rev->available, rev->kq_errno);
if (rev->available == 0) {
- if (rev->kq_eof) {
+ if (rev->pending_eof) {
rev->ready = 0;
rev->eof = 1;
*/
if (rev->available <= 0) {
- if (!rev->kq_eof) {
+ if (!rev->pending_eof) {
rev->ready = 0;
}
#if (HAVE_KQUEUE)
- if ((ngx_event_flags & NGX_HAVE_KQUEUE_EVENT) && wev->kq_eof) {
+ if ((ngx_event_flags & NGX_HAVE_KQUEUE_EVENT) && wev->pending_eof) {
ngx_log_error(NGX_LOG_INFO, c->log, wev->kq_errno,
"kevent() reported about an closed connection");
/* conditional expression is constant */
#pragma warning(disable:4127)
-/* nonstandard extension used : bit field types other than int */
-#pragma warning(disable:4214)
-
/* unreachable code */
#pragma warning(disable:4702)