static ngx_int_t ngx_kqueue_del_event(ngx_event_t *ev, ngx_int_t event, ngx_uint_t flags) { ngx_int_t rc; ngx_event_t *e; ev->active = 0; ev->disabled = 0; ngx_mutex_lock(list_mutex); if (ev->index < nchanges && ((uintptr_t) change_list[ev->index].udata & (uintptr_t) ~1) == (uintptr_t) ev) { ngx_log_debug2(NGX_LOG_DEBUG_EVENT, ev->log, 0, "kevent deleted: %d: ft:%i", ngx_event_ident(ev->data), event); /* if the event is still not passed to a kernel we will not pass it */ nchanges--; if (ev->index < nchanges) { e = (ngx_event_t *) ((uintptr_t) change_list[nchanges].udata & (uintptr_t) ~1); change_list[ev->index] = change_list[nchanges]; e->index = ev->index; } ngx_mutex_unlock(list_mutex); return NGX_OK; } /* * when the file descriptor is closed the 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) { ngx_mutex_unlock(list_mutex); return NGX_OK; } if (flags & NGX_DISABLE_EVENT) { ev->disabled = 1; } else { flags |= EV_DELETE; } rc = ngx_kqueue_set_event(ev, event, flags); ngx_mutex_unlock(list_mutex); return rc; }
ngx_http_cache_t *ngx_http_cache_get(ngx_http_cache_hash_t *hash, ngx_http_cleanup_t *cleanup, ngx_str_t *key, uint32_t *crc) { ngx_uint_t i; ngx_http_cache_t *c; *crc = ngx_crc(key->data, key->len); c = hash->elts + *crc % hash->hash * hash->nelts; if (ngx_mutex_lock(&hash->mutex) == NGX_ERROR) { return (void *) NGX_ERROR; } for (i = 0; i < hash->nelts; i++) { if (c[i].crc == *crc && c[i].key.len == key->len && ngx_rstrncmp(c[i].key.data, key->data, key->len) == 0) { #if 0 if (c[i].expired) { ngx_mutex_unlock(&hash->mutex); return (void *) NGX_AGAIN; } #endif c[i].refs++; if ((!(c[i].notify && (ngx_event_flags & NGX_USE_KQUEUE_EVENT))) && (ngx_cached_time - c[i].updated >= hash->update)) { c[i].expired = 1; } ngx_mutex_unlock(&hash->mutex); if (cleanup) { cleanup->data.cache.hash = hash; cleanup->data.cache.cache = &c[i]; cleanup->valid = 1; cleanup->cache = 1; } return &c[i]; } } ngx_mutex_unlock(&hash->mutex); return NULL; }
void ngx_wakeup_worker_thread(ngx_cycle_t *cycle) { ngx_int_t i; #if 0 ngx_uint_t busy; ngx_event_t *ev; busy = 1; if (ngx_mutex_lock(ngx_posted_events_mutex) == NGX_ERROR) { return; } for (ev = (ngx_event_t *) ngx_posted_events; ev; ev = ev->next) { if (*(ev->lock) == 0) { busy = 0; break; } } ngx_mutex_unlock(ngx_posted_events_mutex); if (busy) { return; } #endif for (i = 0; i < ngx_threads_n; i++) { if (ngx_threads[i].state == NGX_THREAD_FREE) { ngx_cond_signal(ngx_threads[i].cv); return; } } }
ngx_int_t ngx_event_busy_lock_cancel(ngx_event_busy_lock_t *bl, ngx_event_busy_lock_ctx_t *ctx) { ngx_event_busy_lock_ctx_t *c, *p; if (ngx_mutex_lock(bl->mutex) == NGX_ERROR) { return NGX_ERROR; } bl->waiting--; if (ctx == bl->events) { bl->events = ctx->next; } else { p = bl->events; for (c = bl->events->next; c; c = c->next) { if (c == ctx) { p->next = ctx->next; break; } p = c; } } ngx_mutex_unlock(bl->mutex); return NGX_OK; }
void ngx_event_busy_lock_cancel(ngx_event_busy_lock_t *bl, ngx_event_busy_lock_ctx_t *ctx) { ngx_event_busy_lock_ctx_t *c, *p; ngx_mutex_lock(bl->mutex); bl->waiting--; if (ctx == bl->events) { bl->events = ctx->next; } else { p = bl->events; for (c = bl->events->next; c; c = c->next) { if (c == ctx) { p->next = ctx->next; break; } p = c; } } ngx_mutex_unlock(bl->mutex); }
ngx_int_t ngx_libc_crypt(ngx_pool_t *pool, u_char *key, u_char *salt, u_char **encrypted) { char *value; size_t len; ngx_err_t err; #if (NGX_THREADS && NGX_NONREENTRANT_CRYPT) /* crypt() is a time consuming function, so we only try to lock */ if (ngx_mutex_trylock(ngx_crypt_mutex) != NGX_OK) { return NGX_AGAIN; } #endif value = crypt((char *) key, (char *) salt); if (value) { len = ngx_strlen(value) + 1; *encrypted = ngx_pnalloc(pool, len); if (*encrypted == NULL) { #if (NGX_THREADS && NGX_NONREENTRANT_CRYPT) ngx_mutex_unlock(ngx_crypt_mutex); #endif return NGX_ERROR; } ngx_memcpy(*encrypted, value, len); #if (NGX_THREADS && NGX_NONREENTRANT_CRYPT) ngx_mutex_unlock(ngx_crypt_mutex); #endif return NGX_OK; } err = ngx_errno; #if (NGX_THREADS && NGX_NONREENTRANT_CRYPT) ngx_mutex_unlock(ngx_crypt_mutex); #endif ngx_log_error(NGX_LOG_CRIT, pool->log, err, "crypt() failed"); return NGX_ERROR; }
ngx_int_t ngx_event_busy_lock_cachable(ngx_event_busy_lock_t *bl, ngx_event_busy_lock_ctx_t *ctx) { ngx_int_t rc; if (ngx_mutex_lock(bl->mutex) == NGX_ERROR) { return NGX_ERROR; } rc = ngx_event_busy_lock_look_cachable(bl, ctx); ngx_log_debug3(NGX_LOG_DEBUG_EVENT, ctx->event->log, 0, "event busy lock: %d w:%d mw:%d", rc, bl->waiting, bl->max_waiting); /* * NGX_OK: no the same request, there is free slot and we locked it * NGX_BUSY: no the same request and there is no free slot * NGX_AGAIN: the same request is processing */ if (rc == NGX_AGAIN) { if (ctx->timer && bl->waiting < bl->max_waiting) { bl->waiting++; ngx_add_timer(ctx->event, ctx->timer); ctx->event->event_handler = ngx_event_busy_lock_handler; if (bl->events == NULL) { bl->events = ctx; } else { bl->last->next = ctx; } bl->last = ctx; } else { rc = NGX_BUSY; } } ngx_mutex_unlock(bl->mutex); return rc; }
static void ngx_event_busy_lock_handler(ngx_event_t *ev) { if (ngx_mutex_lock(ngx_posted_events_mutex) == NGX_ERROR) { return; } ngx_post_event(ev); ngx_mutex_unlock(ngx_posted_events_mutex); ev->event_handler = ngx_event_busy_lock_posted_handler; }
ngx_int_t ngx_event_busy_lock(ngx_event_busy_lock_t *bl, ngx_event_busy_lock_ctx_t *ctx) { ngx_int_t rc; if (ngx_mutex_lock(bl->mutex) == NGX_ERROR) { return NGX_ERROR; } ngx_log_debug2(NGX_LOG_DEBUG_EVENT, ctx->event->log, 0, "event busy lock: b:%d mb:%d", bl->busy, bl->max_busy); if (bl->busy < bl->max_busy) { bl->busy++; rc = NGX_OK; } else if (ctx->timer && bl->waiting < bl->max_waiting) { bl->waiting++; ngx_add_timer(ctx->event, ctx->timer); ctx->event->event_handler = ngx_event_busy_lock_handler; if (bl->events) { bl->last->next = ctx; } else { bl->events = ctx; } bl->last = ctx; rc = NGX_AGAIN; } else { rc = NGX_BUSY; } ngx_mutex_unlock(bl->mutex); return rc; }
void ngx_http_cache_unlock(ngx_http_cache_hash_t *hash, ngx_http_cache_t *cache, ngx_log_t *log) { if (ngx_mutex_lock(&hash->mutex) == NGX_ERROR) { return; } cache->refs--; if (cache->refs == 0 && cache->deleted) { ngx_http_cache_free(cache, NULL, NULL, log); } ngx_mutex_unlock(&hash->mutex); }
static int ngx_mbedtls_rng(void *data, unsigned char *output, size_t output_len) { int rval; #if (NGX_THREADS) ngx_mutex_lock(ngx_ctr_drbg_mutex); #endif rval = ctr_drbg_random(data, output, output_len); #if (NGX_THREADS) ngx_mutex_unlock(ngx_ctr_drbg_mutex); #endif return rval; }
ngx_msec_t ngx_event_find_timer(void) { ngx_msec_t timer; ngx_rbtree_t *node; if (ngx_event_timer_rbtree == &ngx_event_timer_sentinel) { return NGX_TIMER_INFINITE; } if (ngx_mutex_lock(ngx_event_timer_mutex) == NGX_ERROR) { return NGX_TIMER_ERROR; } node = ngx_rbtree_min((ngx_rbtree_t *) ngx_event_timer_rbtree, &ngx_event_timer_sentinel); ngx_mutex_unlock(ngx_event_timer_mutex); timer = (ngx_msec_t) (node->key * NGX_TIMER_RESOLUTION - ngx_elapsed_msec / NGX_TIMER_RESOLUTION * NGX_TIMER_RESOLUTION); return timer > 0 ? timer: 0 ; }
ngx_int_t ngx_event_thread_process_posted(ngx_cycle_t *cycle) { ngx_event_t *ev; for ( ;; ) { ev = (ngx_event_t *) ngx_posted_events; for ( ;; ) { ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0, "posted event %p", ev); if (ev == NULL) { return NGX_OK; } if (ngx_trylock(ev->lock) == 0) { ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0, "posted event %p is busy", ev); ev = ev->next; continue; } if (ev->lock != ev->own_lock) { if (*(ev->own_lock)) { ngx_log_error(NGX_LOG_ALERT, cycle->log, 0, "the own lock of the posted event %p is busy", ev); ngx_unlock(ev->lock); ev = ev->next; continue; } *(ev->own_lock) = 1; } ngx_delete_posted_event(ev); ev->locked = 1; ev->ready |= ev->posted_ready; ev->timedout |= ev->posted_timedout; ev->pending_eof |= ev->posted_eof; #if (NGX_HAVE_KQUEUE) ev->kq_errno |= ev->posted_errno; #endif if (ev->posted_available) { ev->available = ev->posted_available; } ev->posted_ready = 0; ev->posted_timedout = 0; ev->posted_eof = 0; #if (NGX_HAVE_KQUEUE) ev->posted_errno = 0; #endif ev->posted_available = 0; ngx_mutex_unlock(ngx_posted_events_mutex); ev->handler(ev); ngx_mutex_lock(ngx_posted_events_mutex); if (ev->locked) { ngx_unlock(ev->lock); if (ev->lock != ev->own_lock) { ngx_unlock(ev->own_lock); } } ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0, "posted event %p is done", ev); break; } } }
static ngx_thread_value_t ngx_worker_thread_cycle(void *data) { ngx_thread_t *thr = data; sigset_t set; ngx_err_t err; ngx_core_tls_t *tls; ngx_cycle_t *cycle; cycle = (ngx_cycle_t *) ngx_cycle; 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) { ngx_log_error(NGX_LOG_ALERT, cycle->log, err, ngx_thread_sigmask_n " failed"); return (ngx_thread_value_t) 1; } ngx_log_debug1(NGX_LOG_DEBUG_CORE, cycle->log, 0, "thread " NGX_TID_T_FMT " started", ngx_thread_self()); ngx_setthrtitle("worker thread"); tls = ngx_calloc(sizeof(ngx_core_tls_t), cycle->log); if (tls == NULL) { return (ngx_thread_value_t) 1; } err = ngx_thread_set_tls(ngx_core_tls_key, tls); if (err != 0) { ngx_log_error(NGX_LOG_ALERT, cycle->log, err, ngx_thread_set_tls_n " failed"); return (ngx_thread_value_t) 1; } ngx_mutex_lock(ngx_posted_events_mutex); for ( ;; ) { thr->state = NGX_THREAD_FREE; if (ngx_cond_wait(thr->cv, ngx_posted_events_mutex) == NGX_ERROR) { return (ngx_thread_value_t) 1; } if (ngx_terminate) { thr->state = NGX_THREAD_EXIT; ngx_mutex_unlock(ngx_posted_events_mutex); ngx_log_debug1(NGX_LOG_DEBUG_CORE, cycle->log, 0, "thread " NGX_TID_T_FMT " is done", ngx_thread_self()); return (ngx_thread_value_t) 0; } thr->state = NGX_THREAD_BUSY; if (ngx_event_thread_process_posted(cycle) == NGX_ERROR) { return (ngx_thread_value_t) 1; } if (ngx_event_thread_process_posted(cycle) == NGX_ERROR) { return (ngx_thread_value_t) 1; } if (ngx_process_changes) { if (ngx_process_changes(cycle, 1) == NGX_ERROR) { return (ngx_thread_value_t) 1; } } } }
static ngx_int_t ngx_kqueue_process_events(ngx_cycle_t *cycle, ngx_msec_t timer, ngx_uint_t flags) { int events, n; ngx_int_t i, instance; ngx_uint_t level; ngx_err_t err; ngx_event_t *ev, **queue; struct timespec ts, *tp; if (ngx_threaded) { if (ngx_kqueue_process_changes(cycle, 0) == NGX_ERROR) { return NGX_ERROR; } n = 0; } else { n = (int) nchanges; nchanges = 0; } if (timer == NGX_TIMER_INFINITE) { tp = NULL; } else { ts.tv_sec = timer / 1000; ts.tv_nsec = (timer % 1000) * 1000000; /* * 64-bit Darwin kernel has the bug: kernel level ts.tv_nsec is * the int32_t while user level ts.tv_nsec is the long (64-bit), * so on the big endian PowerPC all nanoseconds are lost. */ #if (NGX_DARWIN_KEVENT_BUG) ts.tv_nsec <<= 32; #endif tp = &ts; } ngx_log_debug2(NGX_LOG_DEBUG_EVENT, cycle->log, 0, "kevent timer: %M, changes: %d", timer, n); events = kevent(ngx_kqueue, change_list, n, event_list, (int) nevents, tp); err = (events == -1) ? ngx_errno : 0; if (flags & NGX_UPDATE_TIME || ngx_event_timer_alarm) { ngx_time_update(); } ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0, "kevent events: %d", events); if (err) { if (err == NGX_EINTR) { if (ngx_event_timer_alarm) { ngx_event_timer_alarm = 0; return NGX_OK; } level = NGX_LOG_INFO; } else { level = NGX_LOG_ALERT; } ngx_log_error(level, cycle->log, err, "kevent() failed"); return NGX_ERROR; } if (events == 0) { if (timer != NGX_TIMER_INFINITE) { return NGX_OK; } ngx_log_error(NGX_LOG_ALERT, cycle->log, 0, "kevent() returned no events without timeout"); return NGX_ERROR; } ngx_mutex_lock(ngx_posted_events_mutex); for (i = 0; i < events; i++) { ngx_kqueue_dump_event(cycle->log, &event_list[i]); if (event_list[i].flags & EV_ERROR) { ngx_log_error(NGX_LOG_ALERT, cycle->log, event_list[i].data, "kevent() error on %d filter:%d flags:%04Xd", event_list[i].ident, event_list[i].filter, event_list[i].flags); continue; } #if (NGX_HAVE_TIMER_EVENT) if (event_list[i].filter == EVFILT_TIMER) { ngx_time_update(); continue; } #endif ev = (ngx_event_t *) event_list[i].udata; switch (event_list[i].filter) { case EVFILT_READ: case EVFILT_WRITE: instance = (uintptr_t) ev & 1; ev = (ngx_event_t *) ((uintptr_t) ev & (uintptr_t) ~1); if (ev->closed || ev->instance != 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 %p", ev); continue; } if (ev->log && (ev->log->log_level & NGX_LOG_DEBUG_CONNECTION)) { ngx_kqueue_dump_event(ev->log, &event_list[i]); } if (ev->oneshot) { ev->active = 0; } #if (NGX_THREADS) if ((flags & NGX_POST_THREAD_EVENTS) && !ev->accept) { ev->posted_ready = 1; ev->posted_available = event_list[i].data; if (event_list[i].flags & EV_EOF) { ev->posted_eof = 1; ev->posted_errno = event_list[i].fflags; } ngx_locked_post_event(ev, &ngx_posted_events); continue; } #endif ev->available = event_list[i].data; if (event_list[i].flags & EV_EOF) { ev->pending_eof = 1; ev->kq_errno = event_list[i].fflags; } ev->ready = 1; break; case EVFILT_VNODE: ev->kq_vnode = 1; break; case EVFILT_AIO: ev->complete = 1; ev->ready = 1; break; default: ngx_log_error(NGX_LOG_ALERT, cycle->log, 0, "unexpected kevent() filter %d", event_list[i].filter); continue; } if (flags & NGX_POST_EVENTS) { queue = (ngx_event_t **) (ev->accept ? &ngx_posted_accept_events: &ngx_posted_events); ngx_locked_post_event(ev, queue); continue; } ev->handler(ev); } ngx_mutex_unlock(ngx_posted_events_mutex); return NGX_OK; }
void ngx_close_connection(ngx_connection_t *c) { ngx_err_t err; ngx_uint_t log_error, level; ngx_socket_t fd; if (c->fd == -1) { ngx_log_error(NGX_LOG_ALERT, c->log, 0, "connection already closed"); return; } if (c->read->timer_set) { ngx_del_timer(c->read); } if (c->write->timer_set) { ngx_del_timer(c->write); } if (ngx_del_conn) { ngx_del_conn(c, NGX_CLOSE_EVENT); } else { if (c->read->active || c->read->disabled) { ngx_del_event(c->read, NGX_READ_EVENT, NGX_CLOSE_EVENT); } if (c->write->active || c->write->disabled) { ngx_del_event(c->write, NGX_WRITE_EVENT, NGX_CLOSE_EVENT); } } #if (NGX_THREADS) /* * we have to clean the connection information before the closing * because another thread may reopen the same file descriptor * before we clean the connection */ ngx_mutex_lock(ngx_posted_events_mutex); if (c->read->prev) { ngx_delete_posted_event(c->read); } if (c->write->prev) { ngx_delete_posted_event(c->write); } c->read->closed = 1; c->write->closed = 1; if (c->single_connection) { ngx_unlock(&c->lock); c->read->locked = 0; c->write->locked = 0; } ngx_mutex_unlock(ngx_posted_events_mutex); #else if (c->read->prev) { ngx_delete_posted_event(c->read); } if (c->write->prev) { ngx_delete_posted_event(c->write); } c->read->closed = 1; c->write->closed = 1; #endif ngx_reusable_connection(c, 0); log_error = c->log_error; ngx_free_connection(c); fd = c->fd; c->fd = (ngx_socket_t) -1; if (ngx_close_socket(fd) == -1) { err = ngx_socket_errno; if (err == NGX_ECONNRESET || err == NGX_ENOTCONN) { switch (log_error) { case NGX_ERROR_INFO: level = NGX_LOG_INFO; break; case NGX_ERROR_ERR: level = NGX_LOG_ERR; break; default: level = NGX_LOG_CRIT; } } else { level = NGX_LOG_CRIT; } /* we use ngx_cycle->log because c->log was in c->pool */ ngx_log_error(level, ngx_cycle->log, err, ngx_close_socket_n " %d failed", fd); } }
static ngx_int_t ngx_select_process_events(ngx_cycle_t *cycle, ngx_msec_t timer, ngx_uint_t flags) { int ready, nready; ngx_uint_t i, found; ngx_err_t err; ngx_event_t *ev, **queue; ngx_connection_t *c; struct timeval tv, *tp; #if !(NGX_WIN32) ngx_uint_t level; #endif #if !(NGX_WIN32) if (max_fd == -1) { for (i = 0; i < nevents; i++) { c = event_index[i]->data; if (max_fd < c->fd) { max_fd = c->fd; } } ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0, "change max_fd: %d", max_fd); } #endif #if (NGX_DEBUG) if (cycle->log->log_level & NGX_LOG_DEBUG_ALL) { for (i = 0; i < nevents; i++) { ev = event_index[i]; c = ev->data; ngx_log_debug2(NGX_LOG_DEBUG_EVENT, cycle->log, 0, "select event: fd:%d wr:%d", c->fd, ev->write); } #if !(NGX_WIN32) ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0, "max_fd: %d", max_fd); #endif } #endif if (timer == NGX_TIMER_INFINITE) { tp = NULL; } else { tv.tv_sec = (long) (timer / 1000); tv.tv_usec = (long) ((timer % 1000) * 1000); tp = &tv; } ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0, "select timer: %M", timer); work_read_fd_set = master_read_fd_set; work_write_fd_set = master_write_fd_set; #if 1 ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0, /* * (void *) disables "dereferencing type-punned * pointer will break strict-aliasing rules */ "select read fd_set: %08Xd", *(int *) (void *) &work_read_fd_set); #endif #if (NGX_WIN32) ready = select(0, &work_read_fd_set, &work_write_fd_set, NULL, tp); #else ready = select(max_fd + 1, &work_read_fd_set, &work_write_fd_set, NULL, tp); #endif if (ready == -1) { err = ngx_socket_errno; } else { err = 0; } if (flags & NGX_UPDATE_TIME) { ngx_time_update(0, 0); } ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0, "select ready %d", ready); #if (NGX_WIN32) if (err) { ngx_log_error(NGX_LOG_ALERT, cycle->log, err, "select() failed"); return NGX_ERROR; } #else if (err) { if (err == NGX_EINTR) { if (ngx_event_timer_alarm) { ngx_event_timer_alarm = 0; return NGX_OK; } level = NGX_LOG_INFO; } else { level = NGX_LOG_ALERT; } ngx_log_error(level, cycle->log, err, "select() failed"); return NGX_ERROR; } #endif if (ready == 0) { if (timer != NGX_TIMER_INFINITE) { return NGX_OK; } ngx_log_error(NGX_LOG_ALERT, cycle->log, 0, "select() returned no events without timeout"); return NGX_ERROR; } ngx_mutex_lock(ngx_posted_events_mutex); nready = 0; for (i = 0; i < nevents; i++) { ev = event_index[i]; c = ev->data; found = 0; if (ev->write) { if (FD_ISSET(c->fd, &work_write_fd_set)) { found = 1; ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0, "select write %d", c->fd); } } else { if (FD_ISSET(c->fd, &work_read_fd_set)) { found = 1; ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0, "select read %d", c->fd); } } if (found) { ev->ready = 1; queue = (ngx_event_t **) (ev->accept ? &ngx_posted_accept_events: &ngx_posted_events); ngx_locked_post_event(ev, queue); nready++; } } ngx_mutex_unlock(ngx_posted_events_mutex); if (ready != nready) { ngx_log_error(NGX_LOG_ALERT, cycle->log, 0, "select ready != events"); } return NGX_OK; }
/* called ngx_process_events_and_timers */ static ngx_int_t ngx_epoll_process_events(ngx_cycle_t *cycle, ngx_msec_t timer, ngx_uint_t flags) { int events; uint32_t revents; ngx_int_t instance, i; ngx_uint_t level; ngx_err_t err; ngx_log_t *log; ngx_event_t *rev, *wev, **queue; ngx_connection_t *c; /* NGX_TIMER_INFINITE == INFTIM */ ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0, "epoll timer: %M", timer); events = epoll_wait(ep, event_list, (int) nevents, timer); err = (events == -1) ? ngx_errno : 0; if (flags & NGX_UPDATE_TIME || ngx_event_timer_alarm) { /* 这里判断是否需要更新系统时间变量 ngx_current_msec */ ngx_time_update(); /* 更新系统时间变量 ngx_current_msec */ } if (err) { if (err == NGX_EINTR) { if (ngx_event_timer_alarm) { ngx_event_timer_alarm = 0; return NGX_OK; } level = NGX_LOG_INFO; } else { level = NGX_LOG_ALERT; } ngx_log_error(level, cycle->log, err, "epoll_wait() failed"); return NGX_ERROR; } if (events == 0) { if (timer != NGX_TIMER_INFINITE) { return NGX_OK; } ngx_log_error(NGX_LOG_ALERT, cycle->log, 0, "epoll_wait() returned no events without timeout"); return NGX_ERROR; } ngx_mutex_lock(ngx_posted_events_mutex); log = cycle->log; for (i = 0; i < events; i++) { c = event_list[i].data.ptr; instance = (uintptr_t) c & 1; //获取stale的标识 c = (ngx_connection_t *) ((uintptr_t) c & (uintptr_t) ~1);//获取链接的指针 rev = c->read; /*如果c-fd为-1则说明fd被关闭,如果rev->instance != instance则表示当前的fd已经被重新使用过了, 也就是说这个event已经是stale的了,所以跳过这个事件,然后进行下一个*/ if (c->fd == -1 || rev->instance != 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, "epoll: stale event %p", c); continue; } #if (NGX_DEBUG0) log = c->log ? c->log : cycle->log; #endif revents = event_list[i].events; ngx_log_debug3(NGX_LOG_DEBUG_EVENT, log, 0, "epoll: fd:%d ev:%04XD d:%p", c->fd, revents, event_list[i].data.ptr); if (revents & (EPOLLERR|EPOLLHUP)) { ngx_log_debug2(NGX_LOG_DEBUG_EVENT, log, 0, "epoll_wait() error on fd:%d ev:%04XD", c->fd, revents); } #if 0 if (revents & ~(EPOLLIN|EPOLLOUT|EPOLLERR|EPOLLHUP)) { ngx_log_error(NGX_LOG_ALERT, log, 0, "strange epoll_wait() events fd:%d ev:%04XD", c->fd, revents); } #endif if ((revents & (EPOLLERR|EPOLLHUP)) && (revents & (EPOLLIN|EPOLLOUT)) == 0) { /* * if the error events were returned without EPOLLIN or EPOLLOUT, * then add these flags to handle the events at least in one * active handler */ revents |= EPOLLIN|EPOLLOUT; } if ((revents & EPOLLIN) && rev->active) { /* 这里需要判断是否connection是否激活了读事件,如果没有这里不需要进行处理 */ if ((flags & NGX_POST_THREAD_EVENTS) && !rev->accept) { rev->posted_ready = 1; } else { rev->ready = 1; } if (flags & NGX_POST_EVENTS) { /* event 是否需要POSTED */ queue = (ngx_event_t **) (rev->accept ? &ngx_posted_accept_events : &ngx_posted_events);/* 根据 accept 来判断,将事件放入到哪个事件队列 */ ngx_locked_post_event(rev, queue);/* 将事件添加队列中*/ } else { rev->handler(rev); /* 调用事件处理函数 */ } } wev = c->write; /* 这里需要判断是否connection是否激活了读事件,如果没有这里不需要进行处理 fd本身的状态变化可能在没有关注EPOLLIN的情况下由于缓冲区的状态变化触发写事件 */ if ((revents & EPOLLOUT) && wev->active) { if (flags & NGX_POST_THREAD_EVENTS) { wev->posted_ready = 1; } else { wev->ready = 1; } if (flags & NGX_POST_EVENTS) { /* 写事件只有ngx_posted_events 事件队列 */ ngx_locked_post_event(wev, &ngx_posted_events); } else { wev->handler(wev); } } } ngx_mutex_unlock(ngx_posted_events_mutex); return NGX_OK; }
static ngx_int_t ngx_epoll_process_events(ngx_cycle_t *cycle, ngx_msec_t timer, ngx_uint_t flags) { int events; uint32_t revents; ngx_int_t instance, i; ngx_uint_t level; ngx_err_t err; ngx_event_t *rev, *wev, **queue; ngx_connection_t *c; /* NGX_TIMER_INFINITE == INFTIM */ ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0, "epoll timer: %M", timer); //Here,we start to epoll wait!!! events = epoll_wait(ep, event_list, (int) nevents, timer); err = (events == -1) ? ngx_errno : 0; if (flags & NGX_UPDATE_TIME || ngx_event_timer_alarm) { ngx_time_update(); } if (err) { if (err == NGX_EINTR) { if (ngx_event_timer_alarm) { ngx_event_timer_alarm = 0; return NGX_OK; } level = NGX_LOG_INFO; } else { level = NGX_LOG_ALERT; } ngx_log_error(level, cycle->log, err, "epoll_wait() failed"); return NGX_ERROR; } if (events == 0) { if (timer != NGX_TIMER_INFINITE) { return NGX_OK; } ngx_log_error(NGX_LOG_ALERT, cycle->log, 0, "epoll_wait() returned no events without timeout"); return NGX_ERROR; } ngx_mutex_lock(ngx_posted_events_mutex); for (i = 0; i < events; i++) {//Here,traverse all the events!!! c = event_list[i].data.ptr; instance = (uintptr_t) c & 1; c = (ngx_connection_t *) ((uintptr_t) c & (uintptr_t) ~1); rev = c->read; if (c->fd == -1 || rev->instance != 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, "epoll: stale event %p", c); continue; } revents = event_list[i].events; ngx_log_debug3(NGX_LOG_DEBUG_EVENT, cycle->log, 0, "epoll: fd:%d ev:%04XD d:%p", c->fd, revents, event_list[i].data.ptr); if (revents & (EPOLLERR|EPOLLHUP)) { ngx_log_debug2(NGX_LOG_DEBUG_EVENT, cycle->log, 0, "epoll_wait() error on fd:%d ev:%04XD", c->fd, revents); } #if 0 if (revents & ~(EPOLLIN|EPOLLOUT|EPOLLERR|EPOLLHUP)) { ngx_log_error(NGX_LOG_ALERT, cycle->log, 0, "strange epoll_wait() events fd:%d ev:%04XD", c->fd, revents); } #endif if ((revents & (EPOLLERR|EPOLLHUP)) && (revents & (EPOLLIN|EPOLLOUT)) == 0) { /* * if the error events were returned without EPOLLIN or EPOLLOUT, * then add these flags to handle the events at least in one * active handler */ revents |= EPOLLIN|EPOLLOUT; } //------------------------------------->Test Isn't read event ready!!! if ((revents & EPOLLIN) && rev->active) { if ((flags & NGX_POST_THREAD_EVENTS) && !rev->accept) { rev->posted_ready = 1; } else { rev->ready = 1;//Set we the read_event has been ready!!! } if (flags & NGX_POST_EVENTS) {//Here,If the read_event is used for accept,we should push the event to ngx_posted_accept_events queue!!! queue = (ngx_event_t **) (rev->accept ? &ngx_posted_accept_events : &ngx_posted_events); ngx_locked_post_event(rev, queue);//Here,post the readly event to ngx_posted_events list!!we will desposit it lately!! } else { rev->handler(rev); } } wev = c->write; //------------------------------------->Test Isn't write event ready!!! if ((revents & EPOLLOUT) && wev->active) { if (flags & NGX_POST_THREAD_EVENTS) { wev->posted_ready = 1; } else { wev->ready = 1; } if (flags & NGX_POST_EVENTS) { ngx_locked_post_event(wev, &ngx_posted_events);//Here,we post the events!!! } else { wev->handler(wev); } } } ngx_mutex_unlock(ngx_posted_events_mutex); return NGX_OK; }
static ngx_int_t ngx_select_process_events(ngx_cycle_t *cycle, ngx_msec_t timer, ngx_uint_t flags) { int ready, nready; ngx_err_t err; ngx_uint_t i, found; ngx_event_t *ev, **queue; struct timeval tv, *tp; ngx_connection_t *c; #if (NGX_DEBUG) if (cycle->log->log_level & NGX_LOG_DEBUG_ALL) { for (i = 0; i < nevents; i++) { ev = event_index[i]; c = ev->data; ngx_log_debug2(NGX_LOG_DEBUG_EVENT, cycle->log, 0, "select event: fd:%d wr:%d", c->fd, ev->write); } } #endif if (timer == NGX_TIMER_INFINITE) { tp = NULL; } else { tv.tv_sec = (long) (timer / 1000); tv.tv_usec = (long) ((timer % 1000) * 1000); tp = &tv; } ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0, "select timer: %M", timer); work_read_fd_set = master_read_fd_set; work_write_fd_set = master_write_fd_set; if (max_read || max_write) { ready = select(0, &work_read_fd_set, &work_write_fd_set, NULL, tp); } else { /* * Winsock select() requires that at least one descriptor set must be * be non-null, and any non-null descriptor set must contain at least * one handle to a socket. Otherwise select() returns WSAEINVAL. */ ngx_msleep(timer); ready = 0; } err = (ready == -1) ? ngx_socket_errno : 0; if (flags & NGX_UPDATE_TIME) { ngx_time_update(); } ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0, "select ready %d", ready); if (err) { ngx_log_error(NGX_LOG_ALERT, cycle->log, err, "select() failed"); if (err == WSAENOTSOCK) { ngx_select_repair_fd_sets(cycle); } return NGX_ERROR; } if (ready == 0) { if (timer != NGX_TIMER_INFINITE) { return NGX_OK; } ngx_log_error(NGX_LOG_ALERT, cycle->log, 0, "select() returned no events without timeout"); return NGX_ERROR; } ngx_mutex_lock(ngx_posted_events_mutex); nready = 0; for (i = 0; i < nevents; i++) { ev = event_index[i]; c = ev->data; found = 0; if (ev->write) { if (FD_ISSET(c->fd, &work_write_fd_set)) { found = 1; ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0, "select write %d", c->fd); } } else { if (FD_ISSET(c->fd, &work_read_fd_set)) { found = 1; ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0, "select read %d", c->fd); } } if (found) { ev->ready = 1; queue = (ngx_event_t **) (ev->accept ? &ngx_posted_accept_events: &ngx_posted_events); ngx_locked_post_event(ev, queue); nready++; } } ngx_mutex_unlock(ngx_posted_events_mutex); if (ready != nready) { ngx_log_error(NGX_LOG_ALERT, cycle->log, 0, "select ready != events: %d:%d", ready, nready); ngx_select_repair_fd_sets(cycle); } return NGX_OK; }
static ngx_int_t ngx_select_process_events(ngx_cycle_t *cycle, ngx_msec_t timer, ngx_uint_t flags) { int ready, nready; ngx_err_t err; ngx_uint_t i, found; ngx_event_t *ev, **queue; struct timeval tv, *tp; ngx_connection_t *c; if (max_fd == -1) { for (i = 0; i < nevents; i++) { c = event_index[i]->data; if (max_fd < c->fd) { max_fd = c->fd; } } ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0, "change max_fd: %d", max_fd); } #if (NGX_DEBUG) if (cycle->log->log_level & NGX_LOG_DEBUG_ALL) { for (i = 0; i < nevents; i++) { ev = event_index[i]; c = ev->data; ngx_log_debug2(NGX_LOG_DEBUG_EVENT, cycle->log, 0, "select event: fd:%d wr:%d", c->fd, ev->write); } ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0, "max_fd: %d", max_fd); } #endif if (timer == NGX_TIMER_INFINITE) { tp = NULL; } else { tv.tv_sec = (long) (timer / 1000); tv.tv_usec = (long) ((timer % 1000) * 1000); tp = &tv; } ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0, "select timer: %M", timer); work_read_fd_set = master_read_fd_set; work_write_fd_set = master_write_fd_set; ready = select(max_fd + 1, &work_read_fd_set, &work_write_fd_set, NULL, tp); err = (ready == -1) ? ngx_errno : 0; if (flags & NGX_UPDATE_TIME || ngx_event_timer_alarm) { ngx_time_update(); } ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0, "select ready %d", ready); if (err) { ngx_uint_t level; if (err == NGX_EINTR) { if (ngx_event_timer_alarm) { ngx_event_timer_alarm = 0; return NGX_OK; } level = NGX_LOG_INFO; } else { level = NGX_LOG_ALERT; } ngx_log_error(level, cycle->log, err, "select() failed"); if (err == NGX_EBADF) { ngx_select_repair_fd_sets(cycle); } return NGX_ERROR; } if (ready == 0) { if (timer != NGX_TIMER_INFINITE) { return NGX_OK; } ngx_log_error(NGX_LOG_ALERT, cycle->log, 0, "select() returned no events without timeout"); return NGX_ERROR; } ngx_mutex_lock(ngx_posted_events_mutex); nready = 0; for (i = 0; i < nevents; i++) { ev = event_index[i]; c = ev->data; found = 0; if (ev->write) { if (FD_ISSET(c->fd, &work_write_fd_set)) { found = 1; ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0, "select write %d", c->fd); } } else { if (FD_ISSET(c->fd, &work_read_fd_set)) { found = 1; ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0, "select read %d", c->fd); } } if (found) { ev->ready = 1; queue = (ngx_event_t **) (ev->accept ? &ngx_posted_accept_events: &ngx_posted_events); ngx_locked_post_event(ev, queue); nready++; } } ngx_mutex_unlock(ngx_posted_events_mutex); if (ready != nready) { ngx_log_error(NGX_LOG_ALERT, cycle->log, 0, "select ready != events: %d:%d", ready, nready); ngx_select_repair_fd_sets(cycle); } return NGX_OK; }
ngx_int_t ngx_event_busy_unlock(ngx_event_busy_lock_t *bl, ngx_event_busy_lock_ctx_t *ctx) { ngx_event_t *ev; ngx_event_busy_lock_ctx_t *wakeup; if (ngx_mutex_lock(bl->mutex) == NGX_ERROR) { return NGX_ERROR; } if (bl->events) { wakeup = bl->events; bl->events = bl->events->next; } else { wakeup = NULL; bl->busy--; } /* * MP: all ctx's and their queue must be in shared memory, * each ctx has pid to wake up */ if (wakeup == NULL) { ngx_mutex_unlock(bl->mutex); return NGX_OK; } if (ctx->md5) { for (wakeup = bl->events; wakeup; wakeup = wakeup->next) { if (wakeup->md5 == NULL || wakeup->slot != ctx->slot) { continue; } wakeup->handler = ngx_event_busy_lock_posted_handler; wakeup->cache_updated = 1; ev = wakeup->event; if (ngx_mutex_lock(ngx_posted_events_mutex) == NGX_ERROR) { return NGX_ERROR; } ngx_post_event(ev); ngx_mutex_unlock(ngx_posted_events_mutex); } ngx_mutex_unlock(bl->mutex); } else { bl->waiting--; ngx_mutex_unlock(bl->mutex); wakeup->handler = ngx_event_busy_lock_posted_handler; wakeup->locked = 1; ev = wakeup->event; if (ev->timer_set) { ngx_del_timer(ev); } if (ngx_mutex_lock(ngx_posted_events_mutex) == NGX_ERROR) { return NGX_ERROR; } ngx_post_event(ev); ngx_mutex_unlock(ngx_posted_events_mutex); } return NGX_OK; }
void ngx_event_expire_timers(ngx_msec_t timer) { ngx_event_t *ev; ngx_rbtree_t *node; if (timer < 0) { /* avoid the endless loop if the time goes backward for some reason */ timer = 0; } for ( ;; ) { if (ngx_event_timer_rbtree == &ngx_event_timer_sentinel) { return; } if (ngx_mutex_lock(ngx_event_timer_mutex) == NGX_ERROR) { return; } node = ngx_rbtree_min((ngx_rbtree_t *) ngx_event_timer_rbtree, &ngx_event_timer_sentinel); if (node->key <= (ngx_msec_t) (ngx_old_elapsed_msec + timer) / NGX_TIMER_RESOLUTION) { ev = (ngx_event_t *) ((char *) node - offsetof(ngx_event_t, rbtree_key)); ngx_log_debug2(NGX_LOG_DEBUG_EVENT, ev->log, 0, "event timer del: %d: %d", ngx_event_ident(ev->data), ev->rbtree_key); ngx_rbtree_delete((ngx_rbtree_t **) &ngx_event_timer_rbtree, &ngx_event_timer_sentinel, (ngx_rbtree_t *) &ev->rbtree_key); ngx_mutex_unlock(ngx_event_timer_mutex); #if (NGX_DEBUG) ev->rbtree_left = NULL; ev->rbtree_right = NULL; ev->rbtree_parent = NULL; #endif ev->timer_set = 0; ev->timedout = 1; ev->event_handler(ev); continue; } break; } ngx_mutex_unlock(ngx_event_timer_mutex); }
int ngx_epoll_process_events(ngx_cycle_t *cycle) { int events; size_t n; ngx_int_t instance, i; ngx_uint_t lock, accept_lock, expire; ngx_err_t err; ngx_log_t *log; ngx_msec_t timer; ngx_event_t *rev, *wev; struct timeval tv; ngx_connection_t *c; ngx_epoch_msec_t delta; for ( ;; ) { timer = ngx_event_find_timer(); #if (NGX_THREADS) if (timer == NGX_TIMER_ERROR) { return NGX_ERROR; } if (timer == NGX_TIMER_INFINITE || timer > 500) { timer = 500; break; } #endif if (timer != 0) { break; } ngx_log_debug0(NGX_LOG_DEBUG_EVENT, cycle->log, 0, "epoll expired timer"); ngx_event_expire_timers((ngx_msec_t) (ngx_elapsed_msec - ngx_old_elapsed_msec)); if (ngx_posted_events && ngx_threaded) { ngx_wakeup_worker_thread(cycle); } } /* NGX_TIMER_INFINITE == INFTIM */ if (timer == NGX_TIMER_INFINITE) { expire = 0; } else { expire = 1; } ngx_old_elapsed_msec = ngx_elapsed_msec; accept_lock = 0; if (ngx_accept_mutex) { if (ngx_accept_disabled > 0) { ngx_accept_disabled--; } else { if (ngx_trylock_accept_mutex(cycle) == NGX_ERROR) { return NGX_ERROR; } if (ngx_accept_mutex_held) { accept_lock = 1; } else if (timer == NGX_TIMER_INFINITE || timer > ngx_accept_mutex_delay) { timer = ngx_accept_mutex_delay; expire = 0; } } } ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0, "epoll timer: %d", timer); events = epoll_wait(ep, event_list, nevents, timer); if (events == -1) { err = ngx_errno; } else { err = 0; } ngx_gettimeofday(&tv); ngx_time_update(tv.tv_sec); delta = ngx_elapsed_msec; ngx_elapsed_msec = (ngx_epoch_msec_t) tv.tv_sec * 1000 + tv.tv_usec / 1000 - ngx_start_msec; if (timer != NGX_TIMER_INFINITE) { delta = ngx_elapsed_msec - delta; ngx_log_debug2(NGX_LOG_DEBUG_EVENT, cycle->log, 0, "epoll timer: %d, delta: %d", timer, (int) delta); } else { 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; } } 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 (events > 0) { if (ngx_mutex_lock(ngx_posted_events_mutex) == NGX_ERROR) { ngx_accept_mutex_unlock(); return NGX_ERROR; } lock = 1; } else { lock =0; } log = cycle->log; for (i = 0; i < events; i++) { c = event_list[i].data.ptr; instance = (uintptr_t) c & 1; c = (ngx_connection_t *) ((uintptr_t) c & (uintptr_t) ~1); rev = c->read; if (c->fd == -1 || rev->instance != 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, "epoll: stale event " PTR_FMT, c); continue; } #if (NGX_DEBUG0) log = c->log ? c->log : cycle->log; #endif ngx_log_debug3(NGX_LOG_DEBUG_EVENT, log, 0, "epoll: fd:%d ev:%04X d:" PTR_FMT, c->fd, event_list[i].events, event_list[i].data); if (event_list[i].events & (EPOLLERR|EPOLLHUP)) { ngx_log_debug2(NGX_LOG_DEBUG_EVENT, log, 0, "epoll_wait() error on fd:%d ev:%04X", c->fd, event_list[i].events); } if (event_list[i].events & ~(EPOLLIN|EPOLLOUT|EPOLLERR|EPOLLHUP)) { ngx_log_error(NGX_LOG_ALERT, log, 0, "strange epoll_wait() events fd:%d ev:%04X", c->fd, event_list[i].events); } wev = c->write; if ((event_list[i].events & (EPOLLOUT|EPOLLERR|EPOLLHUP)) && wev->active) { if (ngx_threaded) { wev->posted_ready = 1; ngx_post_event(wev); } else { wev->ready = 1; if (!ngx_accept_mutex_held) { wev->event_handler(wev); } else { ngx_post_event(wev); } } } /* * 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)) && rev->active) { if (ngx_threaded && !rev->accept) { rev->posted_ready = 1; ngx_post_event(rev); continue; } rev->ready = 1; if (!ngx_threaded && !ngx_accept_mutex_held) { rev->event_handler(rev); } else if (!rev->accept) { ngx_post_event(rev); } else if (ngx_accept_disabled <= 0) { ngx_mutex_unlock(ngx_posted_events_mutex); rev->event_handler(rev); if (ngx_accept_disabled > 0) { ngx_accept_mutex_unlock(); accept_lock = 0; } if (i + 1 == events) { lock = 0; break; } if (ngx_mutex_lock(ngx_posted_events_mutex) == NGX_ERROR) { if (accept_lock) { ngx_accept_mutex_unlock(); } return NGX_ERROR; } } } } if (accept_lock) { ngx_accept_mutex_unlock(); } if (lock) { ngx_mutex_unlock(ngx_posted_events_mutex); } if (expire && delta) { ngx_event_expire_timers((ngx_msec_t) delta); } if (ngx_posted_events) { if (ngx_threaded) { ngx_wakeup_worker_thread(cycle); } else { ngx_event_process_posted(cycle); } } return NGX_OK; }
ngx_http_cache_t *ngx_http_cache_alloc(ngx_http_cache_hash_t *hash, ngx_http_cache_t *cache, ngx_http_cleanup_t *cleanup, ngx_str_t *key, uint32_t crc, ngx_str_t *value, ngx_log_t *log) { time_t old; ngx_uint_t i; ngx_http_cache_t *c; old = ngx_cached_time + 1; c = hash->elts + crc % hash->hash * hash->nelts; if (ngx_mutex_lock(&hash->mutex) == NGX_ERROR) { return (void *) NGX_ERROR; } if (cache == NULL) { /* allocate a new entry */ for (i = 0; i < hash->nelts; i++) { if (c[i].refs > 0) { /* a busy entry */ continue; } if (c[i].key.len == 0) { /* a free entry is found */ cache = &c[i]; break; } /* looking for the oldest cache entry */ if (old > c[i].accessed) { old = c[i].accessed; cache = &c[i]; } } if (cache == NULL) { ngx_mutex_unlock(&hash->mutex); return NULL; } ngx_http_cache_free(cache, key, value, log); if (cache->key.data == NULL) { cache->key.data = ngx_alloc(key->len, log); if (cache->key.data == NULL) { ngx_http_cache_free(cache, NULL, NULL, log); ngx_mutex_unlock(&hash->mutex); return NULL; } } cache->key.len = key->len; ngx_memcpy(cache->key.data, key->data, key->len); } else if (value) { ngx_http_cache_free(cache, key, value, log); } if (value) { if (cache->data.value.data == NULL) { cache->data.value.data = ngx_alloc(value->len, log); if (cache->data.value.data == NULL) { ngx_http_cache_free(cache, NULL, NULL, log); ngx_mutex_unlock(&hash->mutex); return NULL; } } cache->data.value.len = value->len; ngx_memcpy(cache->data.value.data, value->data, value->len); } cache->crc = crc; cache->key.len = key->len; cache->refs = 1; cache->count = 0; cache->deleted = 0; cache->expired = 0; cache->memory = 0; cache->mmap = 0; cache->notify = 0; if (cleanup) { cleanup->data.cache.hash = hash; cleanup->data.cache.cache = cache; cleanup->valid = 1; cleanup->cache = 1; } ngx_mutex_unlock(&hash->mutex); return cache; }
ngx_int_t ngx_devpoll_process_events(ngx_cycle_t *cycle, ngx_msec_t timer, ngx_uint_t flags) { int events, revents, rc; size_t n; ngx_fd_t fd; ngx_err_t err; ngx_int_t i; ngx_uint_t level, instance; ngx_event_t *rev, *wev, **queue; ngx_connection_t *c; struct pollfd pfd; struct dvpoll dvp; /* NGX_TIMER_INFINITE == INFTIM */ ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0, "devpoll timer: %M", timer); if (nchanges) { n = nchanges * sizeof(struct pollfd); if (write(dp, change_list, n) != (ssize_t) n) { ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno, "write(/dev/poll) failed"); return NGX_ERROR; } nchanges = 0; } dvp.dp_fds = event_list; dvp.dp_nfds = (int) nevents; dvp.dp_timeout = timer; events = ioctl(dp, DP_POLL, &dvp); err = (events == -1) ? ngx_errno : 0; if (flags & NGX_UPDATE_TIME || ngx_event_timer_alarm) { ngx_time_update(); } if (err) { if (err == NGX_EINTR) { if (ngx_event_timer_alarm) { ngx_event_timer_alarm = 0; return NGX_OK; } level = NGX_LOG_INFO; } else { level = NGX_LOG_ALERT; } ngx_log_error(level, cycle->log, err, "ioctl(DP_POLL) failed"); return NGX_ERROR; } if (events == 0) { if (timer != NGX_TIMER_INFINITE) { return NGX_OK; } ngx_log_error(NGX_LOG_ALERT, cycle->log, 0, "ioctl(DP_POLL) returned no events without timeout"); return NGX_ERROR; } ngx_mutex_lock(ngx_posted_events_mutex); for (i = 0; i < events; i++) { fd = event_list[i].fd; revents = event_list[i].revents; c = ngx_cycle->files[fd]; if (c == NULL || c->fd == -1) { pfd.fd = fd; pfd.events = 0; pfd.revents = 0; rc = ioctl(dp, DP_ISPOLLED, &pfd); switch (rc) { case -1: ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno, "ioctl(DP_ISPOLLED) failed for socket %d, event %04Xd", fd, revents); break; case 0: ngx_log_error(NGX_LOG_ALERT, cycle->log, 0, "phantom event %04Xd for closed and removed socket %d", revents, fd); break; default: ngx_log_error(NGX_LOG_ALERT, cycle->log, 0, "unexpected event %04Xd for closed and removed socket %d, ", "ioctl(DP_ISPOLLED) returned rc:%d, fd:%d, event %04Xd", revents, fd, rc, pfd.fd, pfd.revents); pfd.fd = fd; pfd.events = POLLREMOVE; pfd.revents = 0; if (write(dp, &pfd, sizeof(struct pollfd)) != (ssize_t) sizeof(struct pollfd)) { ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno, "write(/dev/poll) for %d failed", fd); } if (close(fd) == -1) { ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno, "close(%d) failed", fd); } break; } continue; } ngx_log_debug3(NGX_LOG_DEBUG_EVENT, cycle->log, 0, "devpoll: fd:%d, ev:%04Xd, rev:%04Xd", fd, event_list[i].events, revents); if (revents & (POLLERR|POLLHUP|POLLNVAL)) { ngx_log_debug3(NGX_LOG_DEBUG_EVENT, cycle->log, 0, "ioctl(DP_POLL) error fd:%d ev:%04Xd rev:%04Xd", fd, event_list[i].events, revents); } if (revents & ~(POLLIN|POLLOUT|POLLERR|POLLHUP|POLLNVAL)) { ngx_log_error(NGX_LOG_ALERT, cycle->log, 0, "strange ioctl(DP_POLL) events " "fd:%d ev:%04Xd rev:%04Xd", fd, event_list[i].events, revents); } if ((revents & (POLLERR|POLLHUP|POLLNVAL)) && (revents & (POLLIN|POLLOUT)) == 0) { /* * if the error events were returned without POLLIN or POLLOUT, * then add these flags to handle the events at least in one * active handler */ revents |= POLLIN|POLLOUT; } rev = c->read; if ((revents & POLLIN) && rev->active) { if ((flags & NGX_POST_THREAD_EVENTS) && !rev->accept) { rev->posted_ready = 1; } else { rev->ready = 1; } if (flags & NGX_POST_EVENTS) { queue = (ngx_event_t **) (rev->accept ? &ngx_posted_accept_events : &ngx_posted_events); ngx_locked_post_event(rev, queue); } else { instance = rev->instance; rev->handler(rev); if (c->fd == -1 || rev->instance != instance) { continue; } } } wev = c->write; if ((revents & POLLOUT) && wev->active) { if (flags & NGX_POST_THREAD_EVENTS) { wev->posted_ready = 1; } else { wev->ready = 1; } if (flags & NGX_POST_EVENTS) { ngx_locked_post_event(wev, &ngx_posted_events); } else { wev->handler(wev); } } } ngx_mutex_unlock(ngx_posted_events_mutex); return NGX_OK; }
int ngx_devpoll_process_events(ngx_cycle_t *cycle) { int events; ngx_int_t i; ngx_uint_t j, lock, accept_lock, expire; size_t n; ngx_msec_t timer; ngx_err_t err; ngx_cycle_t **old_cycle; ngx_event_t *rev, *wev; ngx_connection_t *c; ngx_epoch_msec_t delta; struct dvpoll dvp; struct timeval tv; for ( ;; ) { timer = ngx_event_find_timer(); if (timer != 0) { break; } ngx_log_debug0(NGX_LOG_DEBUG_EVENT, cycle->log, 0, "devpoll expired timer"); ngx_event_expire_timers((ngx_msec_t) (ngx_elapsed_msec - ngx_old_elapsed_msec)); } /* NGX_TIMER_INFINITE == INFTIM */ if (timer == NGX_TIMER_INFINITE) { expire = 0; } else { expire = 1; } ngx_old_elapsed_msec = ngx_elapsed_msec; accept_lock = 0; if (ngx_accept_mutex) { if (ngx_accept_disabled > 0) { ngx_accept_disabled--; } else { if (ngx_trylock_accept_mutex(cycle) == NGX_ERROR) { return NGX_ERROR; } if (ngx_accept_mutex_held) { accept_lock = 1; } else if (timer == NGX_TIMER_INFINITE || timer > ngx_accept_mutex_delay) { timer = ngx_accept_mutex_delay; expire = 0; } } } ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0, "devpoll timer: %d", timer); if (nchanges) { n = nchanges * sizeof(struct pollfd); if (write(dp, change_list, n) != (ssize_t) n) { ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno, "write(/dev/poll) failed"); ngx_accept_mutex_unlock(); return NGX_ERROR; } } dvp.dp_fds = event_list; dvp.dp_nfds = nevents; dvp.dp_timeout = timer; events = ioctl(dp, DP_POLL, &dvp); if (events == -1) { err = ngx_errno; } else { err = 0; } nchanges = 0; ngx_gettimeofday(&tv); ngx_time_update(tv.tv_sec); delta = ngx_elapsed_msec; ngx_elapsed_msec = (ngx_epoch_msec_t) tv.tv_sec * 1000 + tv.tv_usec / 1000 - ngx_start_msec; if (err) { ngx_log_error((err == NGX_EINTR) ? NGX_LOG_INFO : NGX_LOG_ALERT, cycle->log, err, "ioctl(DP_POLL) failed"); ngx_accept_mutex_unlock(); return NGX_ERROR; } if (timer != NGX_TIMER_INFINITE) { delta = ngx_elapsed_msec - delta; ngx_log_debug2(NGX_LOG_DEBUG_EVENT, cycle->log, 0, "devpoll timer: %d, delta: %d", timer, (int) delta); } else { if (events == 0) { ngx_log_error(NGX_LOG_ALERT, cycle->log, 0, "ioctl(DP_POLL) returned no events without timeout"); 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 = &ngx_cycle->connections[event_list[i].fd]; if (c->fd == -1) { old_cycle = ngx_old_cycles.elts; for (j = 0; j < ngx_old_cycles.nelts; j++) { if (old_cycle[j] == NULL) { continue; } c = &old_cycle[j]->connections[event_list[i].fd]; if (c->fd != -1) { break; } } } if (c->fd == -1) { ngx_log_error(NGX_LOG_EMERG, cycle->log, 0, "unknown cycle"); exit(1); } ngx_log_debug3(NGX_LOG_DEBUG_EVENT, cycle->log, 0, "devpoll: fd:%d, ev:%04X, rev:%04X", event_list[i].fd, event_list[i].events, event_list[i].revents); if (event_list[i].revents & (POLLERR|POLLHUP|POLLNVAL)) { ngx_log_error(NGX_LOG_ALERT, cycle->log, 0, "ioctl(DP_POLL) error fd:%d ev:%04X rev:%04X", event_list[i].fd, event_list[i].events, event_list[i].revents); } if (event_list[i].revents & ~(POLLIN|POLLOUT|POLLERR|POLLHUP|POLLNVAL)) { ngx_log_error(NGX_LOG_ALERT, cycle->log, 0, "strange ioctl(DP_POLL) events " "fd:%d ev:%04X rev:%04X", event_list[i].fd, event_list[i].events, event_list[i].revents); } wev = c->write; if ((event_list[i].events & (POLLOUT|POLLERR|POLLHUP)) && wev->active) { wev->ready = 1; if (!ngx_threaded && !ngx_accept_mutex_held) { wev->event_handler(wev); } else { ngx_post_event(wev); } } /* * POLLIN must be handled after POLLOUT because we use * the optimization to avoid the unnecessary mutex locking/unlocking * if the accept event is the last one. */ rev = c->read; if ((event_list[i].events & (POLLIN|POLLERR|POLLHUP)) && rev->active) { rev->ready = 1; if (!ngx_threaded && !ngx_accept_mutex_held) { rev->event_handler(rev); } else if (!rev->accept) { ngx_post_event(rev); } else if (ngx_accept_disabled <= 0) { ngx_mutex_unlock(ngx_posted_events_mutex); c->read->event_handler(rev); if (ngx_accept_disabled > 0) { ngx_accept_mutex_unlock(); accept_lock = 0; } if (i + 1 == events) { lock = 0; break; } if (ngx_mutex_lock(ngx_posted_events_mutex) == NGX_ERROR) { if (accept_lock) { ngx_accept_mutex_unlock(); } return NGX_ERROR; } } } } if (accept_lock) { ngx_accept_mutex_unlock(); } if (lock) { ngx_mutex_unlock(ngx_posted_events_mutex); } if (expire && delta) { ngx_event_expire_timers((ngx_msec_t) delta); } if (!ngx_threaded) { ngx_event_process_posted(cycle); } return NGX_OK; }
static ngx_int_t ngx_select_process_events(ngx_cycle_t *cycle) { int ready, nready; ngx_uint_t i, found, lock, expire; ngx_err_t err; ngx_msec_t timer; ngx_event_t *ev; ngx_connection_t *c; ngx_epoch_msec_t delta; struct timeval tv, *tp; #if (HAVE_SELECT_CHANGE_TIMEOUT) static ngx_epoch_msec_t deltas = 0; #endif for ( ;; ) { timer = ngx_event_find_timer(); if (timer != 0) { break; } ngx_log_debug0(NGX_LOG_DEBUG_EVENT, cycle->log, 0, "select expired timer"); ngx_event_expire_timers((ngx_msec_t) (ngx_elapsed_msec - ngx_old_elapsed_msec)); } ngx_old_elapsed_msec = ngx_elapsed_msec; expire = 1; #if !(WIN32) if (ngx_accept_mutex) { if (ngx_accept_disabled > 0) { ngx_accept_disabled--; } else { if (ngx_trylock_accept_mutex(cycle) == NGX_ERROR) { return NGX_ERROR; } if (ngx_accept_mutex_held == 0 && (timer == NGX_TIMER_INFINITE || timer > ngx_accept_mutex_delay)) { timer = ngx_accept_mutex_delay; expire = 0; } } } if (max_fd == -1) { for (i = 0; i < nevents; i++) { c = event_index[i]->data; if (max_fd < c->fd) { max_fd = c->fd; } } ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0, "change max_fd: %d", max_fd); } #endif #if (NGX_DEBUG) if (cycle->log->log_level & NGX_LOG_DEBUG_ALL) { for (i = 0; i < nevents; i++) { ev = event_index[i]; c = ev->data; ngx_log_debug2(NGX_LOG_DEBUG_EVENT, cycle->log, 0, "select event: fd:%d wr:%d", c->fd, ev->write); } #if !(WIN32) ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0, "max_fd: %d", max_fd); #endif } #endif if (timer == NGX_TIMER_INFINITE) { tp = NULL; expire = 0; } else { tv.tv_sec = timer / 1000; tv.tv_usec = (timer % 1000) * 1000; tp = &tv; } ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0, "select timer: %d", timer); work_read_fd_set = master_read_fd_set; work_write_fd_set = master_write_fd_set; ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0, "select read fd_set: %08X", *(int *) &work_read_fd_set); #if (WIN32) ready = select(0, &work_read_fd_set, &work_write_fd_set, NULL, tp); #else ready = select(max_fd + 1, &work_read_fd_set, &work_write_fd_set, NULL, tp); #endif if (ready == -1) { err = ngx_socket_errno; } else { err = 0; } #if (HAVE_SELECT_CHANGE_TIMEOUT) if (timer != NGX_TIMER_INFINITE) { delta = timer - (tv.tv_sec * 1000 + tv.tv_usec / 1000); /* * learn the real time and update the cached time * if the sum of the last deltas overcomes 1 second */ deltas += delta; if (deltas > 1000) { ngx_gettimeofday(&tv); ngx_time_update(tv.tv_sec); deltas = tv.tv_usec / 1000; ngx_elapsed_msec = (ngx_epoch_msec_t) tv.tv_sec * 1000 + tv.tv_usec / 1000 - ngx_start_msec; } else { ngx_elapsed_msec += delta; } ngx_log_debug2(NGX_LOG_DEBUG_EVENT, cycle->log, 0, "select timer: %d, delta: %d", timer, (int) delta); } else { delta = 0; ngx_gettimeofday(&tv); ngx_time_update(tv.tv_sec); ngx_elapsed_msec = (ngx_epoch_msec_t) tv.tv_sec * 1000 + tv.tv_usec / 1000 - ngx_start_msec; if (ready == 0) { ngx_log_error(NGX_LOG_ALERT, cycle->log, 0, "select() returned no events without timeout"); ngx_accept_mutex_unlock(); return NGX_ERROR; } } #else /* !(HAVE_SELECT_CHANGE_TIMEOUT) */ ngx_gettimeofday(&tv); ngx_time_update(tv.tv_sec); delta = ngx_elapsed_msec; ngx_elapsed_msec = (ngx_epoch_msec_t) tv.tv_sec * 1000 + tv.tv_usec / 1000 - ngx_start_msec; if (timer != NGX_TIMER_INFINITE) { delta = ngx_elapsed_msec - delta; ngx_log_debug2(NGX_LOG_DEBUG_EVENT, cycle->log, 0, "select timer: %d, delta: %d", timer, (int) delta); } else { if (ready == 0) { ngx_log_error(NGX_LOG_ALERT, cycle->log, 0, "select() returned no events without timeout"); ngx_accept_mutex_unlock(); return NGX_ERROR; } } #endif /* HAVE_SELECT_CHANGE_TIMEOUT */ ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0, "select ready %d", ready); if (err) { #if (WIN32) ngx_log_error(NGX_LOG_ALERT, cycle->log, err, "select() failed"); #else ngx_log_error((err == NGX_EINTR) ? NGX_LOG_INFO : NGX_LOG_ALERT, cycle->log, err, "select() failed"); #endif 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; nready = 0; for (i = 0; i < nevents; i++) { ev = event_index[i]; c = ev->data; found = 0; if (ev->write) { if (FD_ISSET(c->fd, &work_write_fd_set)) { found = 1; ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0, "select write %d", c->fd); } } else { if (FD_ISSET(c->fd, &work_read_fd_set)) { found = 1; ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0, "select read %d", c->fd); } } if (found) { ev->ready = 1; if (ev->oneshot) { if (ev->timer_set) { ngx_del_timer(ev); } if (ev->write) { ngx_select_del_event(ev, NGX_WRITE_EVENT, 0); } else { ngx_select_del_event(ev, NGX_READ_EVENT, 0); } } if (ev->accept) { ev->next = accept_events; accept_events = ev; } else { ngx_post_event(ev); } nready++; } } ev = accept_events; for ( ;; ) { ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0, "accept event " PTR_FMT, ev); if (ev == NULL) { break; } ngx_mutex_unlock(ngx_posted_events_mutex); ev->event_handler(ev); if (ngx_accept_disabled > 0) { lock = 0; break; } ev = ev->next; if (ev == NULL) { lock = 0; break; } if (ngx_mutex_lock(ngx_posted_events_mutex) == NGX_ERROR) { ngx_accept_mutex_unlock(); return NGX_ERROR; } } ngx_accept_mutex_unlock(); accept_events = NULL; if (lock) { ngx_mutex_unlock(ngx_posted_events_mutex); } if (ready != nready) { ngx_log_error(NGX_LOG_ALERT, cycle->log, 0, "select ready != events"); } if (expire && delta) { ngx_event_expire_timers((ngx_msec_t) delta); } if (!ngx_threaded) { ngx_event_process_posted(cycle); } return NGX_OK; }
static ngx_int_t ngx_rtsig_process_overflow(ngx_cycle_t *cycle, ngx_msec_t timer, ngx_uint_t flags) { int name[2], rtsig_max, rtsig_nr, events, ready; size_t len; ngx_err_t err; ngx_uint_t tested, n, i; ngx_event_t *rev, *wev, **queue; ngx_connection_t *c; ngx_rtsig_conf_t *rtscf; ngx_log_debug0(NGX_LOG_DEBUG_EVENT, cycle->log, 0, "rtsig process overflow"); rtscf = ngx_event_get_conf(ngx_cycle->conf_ctx, ngx_rtsig_module); tested = 0; for ( ;; ) { n = 0; while (n < rtscf->overflow_events) { if (overflow_current == cycle->connection_n) { break; } c = cycle->files[overflow_current++]; if (c == NULL || c->fd == -1) { continue; } events = 0; if (c->read->active && c->read->handler) { events |= POLLIN; } if (c->write->active && c->write->handler) { events |= POLLOUT; } if (events == 0) { continue; } overflow_list[n].fd = c->fd; overflow_list[n].events = events; overflow_list[n].revents = 0; n++; } if (n == 0) { break; } for ( ;; ) { ready = poll(overflow_list, n, 0); ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0, "rtsig overflow poll:%d", ready); if (ready == -1) { err = ngx_errno; ngx_log_error((err == NGX_EINTR) ? NGX_LOG_INFO : NGX_LOG_ALERT, cycle->log, 0, "poll() failed while the overflow recover"); if (err == NGX_EINTR) { continue; } } break; } if (ready <= 0) { continue; } ngx_mutex_lock(ngx_posted_events_mutex); for (i = 0; i < n; i++) { c = cycle->files[overflow_list[i].fd]; if (c == NULL) { continue; } rev = c->read; if (rev->active && !rev->closed && rev->handler && (overflow_list[i].revents & (POLLIN|POLLERR|POLLHUP|POLLNVAL))) { tested++; if ((flags & NGX_POST_THREAD_EVENTS) && !rev->accept) { rev->posted_ready = 1; } else { rev->ready = 1; } if (flags & NGX_POST_EVENTS) { queue = (ngx_event_t **) (rev->accept ? &ngx_posted_accept_events : &ngx_posted_events); ngx_locked_post_event(rev, queue); } else { rev->handler(rev); } } wev = c->write; if (wev->active && !wev->closed && wev->handler && (overflow_list[i].revents & (POLLOUT|POLLERR|POLLHUP|POLLNVAL))) { tested++; if (flags & NGX_POST_THREAD_EVENTS) { wev->posted_ready = 1; } else { wev->ready = 1; } if (flags & NGX_POST_EVENTS) { ngx_locked_post_event(wev, &ngx_posted_events); } else { wev->handler(wev); } } } ngx_mutex_unlock(ngx_posted_events_mutex); if (tested >= rtscf->overflow_test) { if (ngx_linux_rtsig_max) { /* * Check the current rt queue length to prevent * the new overflow. * * learn the "/proc/sys/kernel/rtsig-max" value because * it can be changed since the last checking */ name[0] = CTL_KERN; name[1] = KERN_RTSIGMAX; len = sizeof(rtsig_max); if (sysctl(name, 2, &rtsig_max, &len, NULL, 0) == -1) { ngx_log_error(NGX_LOG_ALERT, cycle->log, errno, "sysctl(KERN_RTSIGMAX) failed"); return NGX_ERROR; } /* name[0] = CTL_KERN; */ name[1] = KERN_RTSIGNR; len = sizeof(rtsig_nr); if (sysctl(name, 2, &rtsig_nr, &len, NULL, 0) == -1) { ngx_log_error(NGX_LOG_ALERT, cycle->log, errno, "sysctl(KERN_RTSIGNR) failed"); return NGX_ERROR; } /* * drain the rt signal queue if the /"proc/sys/kernel/rtsig-nr" * is bigger than * "/proc/sys/kernel/rtsig-max" / "rtsig_overflow_threshold" */ if (rtsig_max / (int) rtscf->overflow_threshold < rtsig_nr) { ngx_log_debug2(NGX_LOG_DEBUG_EVENT, cycle->log, 0, "rtsig queue state: %d/%d", rtsig_nr, rtsig_max); while (ngx_rtsig_process_events(cycle, 0, flags) == NGX_OK) { /* void */ } } } else { /* * Linux has not KERN_RTSIGMAX since 2.6.6-mm2 * so drain the rt signal queue unconditionally */ while (ngx_rtsig_process_events(cycle, 0, flags) == NGX_OK) { /* void */ } } tested = 0; } } if (flags & NGX_UPDATE_TIME) { ngx_time_update(); } ngx_log_error(NGX_LOG_ALERT, cycle->log, 0, "rt signal queue overflow recovered"); overflow = 0; ngx_event_actions.process_events = ngx_rtsig_process_events; return NGX_OK; }
ngx_int_t ngx_eventport_process_events(ngx_cycle_t *cycle, ngx_msec_t timer, ngx_uint_t flags) { int n, revents; u_int events; ngx_err_t err; ngx_int_t instance; ngx_uint_t i, level; ngx_event_t *ev, *rev, *wev, **queue; ngx_connection_t *c; struct timespec ts, *tp; if (timer == NGX_TIMER_INFINITE) { tp = NULL; } else { ts.tv_sec = timer / 1000; ts.tv_nsec = (timer % 1000) * 1000000; tp = &ts; } ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0, "eventport timer: %M", timer); events = 1; n = port_getn(ep, event_list, (u_int) nevents, &events, tp); err = ngx_errno; if (flags & NGX_UPDATE_TIME) { ngx_time_update(); } if (n == -1) { if (err == ETIME) { if (timer != NGX_TIMER_INFINITE) { return NGX_OK; } ngx_log_error(NGX_LOG_ALERT, cycle->log, 0, "port_getn() returned no events without timeout"); return NGX_ERROR; } level = (err == NGX_EINTR) ? NGX_LOG_INFO : NGX_LOG_ALERT; ngx_log_error(level, cycle->log, err, "port_getn() failed"); return NGX_ERROR; } if (events == 0) { if (timer != NGX_TIMER_INFINITE) { return NGX_OK; } ngx_log_error(NGX_LOG_ALERT, cycle->log, 0, "port_getn() returned no events without timeout"); return NGX_ERROR; } ngx_mutex_lock(ngx_posted_events_mutex); for (i = 0; i < events; i++) { if (event_list[i].portev_source == PORT_SOURCE_TIMER) { ngx_time_update(); continue; } ev = event_list[i].portev_user; switch (event_list[i].portev_source) { case PORT_SOURCE_FD: instance = (uintptr_t) ev & 1; ev = (ngx_event_t *) ((uintptr_t) ev & (uintptr_t) ~1); if (ev->closed || ev->instance != 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, "eventport: stale event %p", ev); continue; } revents = event_list[i].portev_events; ngx_log_debug2(NGX_LOG_DEBUG_EVENT, cycle->log, 0, "eventport: fd:%d, ev:%04Xd", event_list[i].portev_object, revents); if (revents & (POLLERR|POLLHUP|POLLNVAL)) { ngx_log_debug2(NGX_LOG_DEBUG_EVENT, cycle->log, 0, "port_getn() error fd:%d ev:%04Xd", event_list[i].portev_object, revents); } if (revents & ~(POLLIN|POLLOUT|POLLERR|POLLHUP|POLLNVAL)) { ngx_log_error(NGX_LOG_ALERT, cycle->log, 0, "strange port_getn() events fd:%d ev:%04Xd", event_list[i].portev_object, revents); } if ((revents & (POLLERR|POLLHUP|POLLNVAL)) && (revents & (POLLIN|POLLOUT)) == 0) { /* * if the error events were returned without POLLIN or POLLOUT, * then add these flags to handle the events at least in one * active handler */ revents |= POLLIN|POLLOUT; } c = ev->data; rev = c->read; wev = c->write; rev->active = 0; wev->active = 0; if (revents & POLLIN) { if ((flags & NGX_POST_THREAD_EVENTS) && !rev->accept) { rev->posted_ready = 1; } else { rev->ready = 1; } if (flags & NGX_POST_EVENTS) { queue = (ngx_event_t **) (rev->accept ? &ngx_posted_accept_events : &ngx_posted_events); ngx_locked_post_event(rev, queue); } else { rev->handler(rev); if (ev->closed) { continue; } } if (rev->accept) { if (ngx_use_accept_mutex) { ngx_accept_events = 1; continue; } if (port_associate(ep, PORT_SOURCE_FD, c->fd, POLLIN, (void *) ((uintptr_t) ev | ev->instance)) == -1) { ngx_log_error(NGX_LOG_ALERT, ev->log, ngx_errno, "port_associate() failed"); return NGX_ERROR; } } } if (revents & POLLOUT) { if (flags & NGX_POST_THREAD_EVENTS) { wev->posted_ready = 1; } else { wev->ready = 1; } if (flags & NGX_POST_EVENTS) { ngx_locked_post_event(wev, &ngx_posted_events); } else { wev->handler(wev); } } continue; default: ngx_log_error(NGX_LOG_ALERT, cycle->log, 0, "unexpected even_port object %d", event_list[i].portev_object); continue; } } ngx_mutex_unlock(ngx_posted_events_mutex); return NGX_OK; }