Mercurial > hg > nginx-vendor-0-8
view src/event/ngx_event.c @ 196:8759b346e431 NGINX_0_3_45
nginx 0.3.45
*) Feature: the "ssl_verify_client", "ssl_verify_depth", and
"ssl_client_certificate" directives.
*) Change: the $request_method variable now returns the main request
method.
*) Change: the ° symbol codes were changed in koi-win conversion
table.
*) Feature: the euro É N symbols were added to koi-win conversion table.
*) Bugfix: if nginx distributed the requests among several backends and
some backend failed, then requests intended for this backend was
directed to one live backend only instead of being distributed among
the rest.
author | Igor Sysoev <http://sysoev.ru> |
---|---|
date | Sat, 06 May 2006 00:00:00 +0400 |
parents | 3689cd4e3228 |
children | 56688ed172c8 |
line wrap: on
line source
/* * Copyright (C) Igor Sysoev */ #include <ngx_config.h> #include <ngx_core.h> #include <ngx_event.h> #define DEFAULT_CONNECTIONS 512 extern ngx_module_t ngx_kqueue_module; extern ngx_module_t ngx_devpoll_module; extern ngx_module_t ngx_epoll_module; extern ngx_module_t ngx_rtsig_module; extern ngx_module_t ngx_select_module; static ngx_int_t ngx_event_module_init(ngx_cycle_t *cycle); static ngx_int_t ngx_event_process_init(ngx_cycle_t *cycle); static char *ngx_events_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); static char *ngx_event_connections(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); static char *ngx_event_use(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); static char *ngx_event_debug_connection(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); static void *ngx_event_create_conf(ngx_cycle_t *cycle); static char *ngx_event_init_conf(ngx_cycle_t *cycle, void *conf); static ngx_uint_t ngx_timer_resolution; sig_atomic_t ngx_event_timer_alarm; static ngx_uint_t ngx_event_max_module; ngx_uint_t ngx_event_flags; ngx_event_actions_t ngx_event_actions; ngx_atomic_t connection_counter = 1; ngx_atomic_t *ngx_connection_counter = &connection_counter; ngx_atomic_t *ngx_accept_mutex_ptr; ngx_shmtx_t ngx_accept_mutex; ngx_uint_t ngx_use_accept_mutex; ngx_uint_t ngx_accept_mutex_held; ngx_msec_t ngx_accept_mutex_delay; ngx_int_t ngx_accept_disabled; ngx_file_t ngx_accept_mutex_lock_file; #if (NGX_STAT_STUB) ngx_atomic_t ngx_stat_accepted0; ngx_atomic_t *ngx_stat_accepted = &ngx_stat_accepted0; ngx_atomic_t ngx_stat_handled0; ngx_atomic_t *ngx_stat_handled = &ngx_stat_handled0; ngx_atomic_t ngx_stat_requests0; ngx_atomic_t *ngx_stat_requests = &ngx_stat_requests0; ngx_atomic_t ngx_stat_active0; ngx_atomic_t *ngx_stat_active = &ngx_stat_active0; ngx_atomic_t ngx_stat_reading0; ngx_atomic_t *ngx_stat_reading = &ngx_stat_reading0; ngx_atomic_t ngx_stat_writing0; ngx_atomic_t *ngx_stat_writing = &ngx_stat_writing0; #endif static ngx_command_t ngx_events_commands[] = { { ngx_string("events"), NGX_MAIN_CONF|NGX_CONF_BLOCK|NGX_CONF_NOARGS, ngx_events_block, 0, 0, NULL }, ngx_null_command }; static ngx_core_module_t ngx_events_module_ctx = { ngx_string("events"), NULL, NULL }; ngx_module_t ngx_events_module = { NGX_MODULE_V1, &ngx_events_module_ctx, /* module context */ ngx_events_commands, /* module directives */ NGX_CORE_MODULE, /* module type */ NULL, /* init master */ NULL, /* init module */ NULL, /* init process */ NULL, /* init thread */ NULL, /* exit thread */ NULL, /* exit process */ NULL, /* exit master */ NGX_MODULE_V1_PADDING }; static ngx_str_t event_core_name = ngx_string("event_core"); static ngx_command_t ngx_event_core_commands[] = { { ngx_string("worker_connections"), NGX_EVENT_CONF|NGX_CONF_TAKE1, ngx_event_connections, 0, 0, NULL }, { ngx_string("connections"), NGX_EVENT_CONF|NGX_CONF_TAKE1, ngx_event_connections, 0, 0, NULL }, { ngx_string("use"), NGX_EVENT_CONF|NGX_CONF_TAKE1, ngx_event_use, 0, 0, NULL }, { ngx_string("multi_accept"), NGX_EVENT_CONF|NGX_CONF_TAKE1, ngx_conf_set_flag_slot, 0, offsetof(ngx_event_conf_t, multi_accept), NULL }, { ngx_string("accept_mutex"), NGX_EVENT_CONF|NGX_CONF_TAKE1, ngx_conf_set_flag_slot, 0, offsetof(ngx_event_conf_t, accept_mutex), NULL }, { ngx_string("accept_mutex_delay"), NGX_EVENT_CONF|NGX_CONF_TAKE1, ngx_conf_set_msec_slot, 0, offsetof(ngx_event_conf_t, accept_mutex_delay), NULL }, { ngx_string("debug_connection"), NGX_EVENT_CONF|NGX_CONF_TAKE1, ngx_event_debug_connection, 0, 0, NULL }, ngx_null_command }; ngx_event_module_t ngx_event_core_module_ctx = { &event_core_name, ngx_event_create_conf, /* create configuration */ ngx_event_init_conf, /* init configuration */ { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL } }; ngx_module_t ngx_event_core_module = { NGX_MODULE_V1, &ngx_event_core_module_ctx, /* module context */ ngx_event_core_commands, /* module directives */ NGX_EVENT_MODULE, /* module type */ NULL, /* init master */ ngx_event_module_init, /* init module */ ngx_event_process_init, /* init process */ NULL, /* init thread */ NULL, /* exit thread */ NULL, /* exit process */ NULL, /* exit master */ NGX_MODULE_V1_PADDING }; void ngx_process_events_and_timers(ngx_cycle_t *cycle) { ngx_uint_t flags; ngx_msec_t timer, delta; if (ngx_timer_resolution) { timer = NGX_TIMER_INFINITE; flags = 0; } else { timer = ngx_event_find_timer(); flags = NGX_UPDATE_TIME; #if (NGX_THREADS) if (timer == NGX_TIMER_INFINITE || timer > 500) { timer = 500; } #endif } if (ngx_use_accept_mutex) { if (ngx_accept_disabled > 0) { ngx_accept_disabled--; } else { if (ngx_trylock_accept_mutex(cycle) == NGX_ERROR) { return; } if (ngx_accept_mutex_held) { flags |= NGX_POST_EVENTS; } else { if (timer == NGX_TIMER_INFINITE || timer > ngx_accept_mutex_delay) { timer = ngx_accept_mutex_delay; } } } } delta = ngx_current_msec; (void) ngx_process_events(cycle, timer, flags); delta = ngx_current_msec - delta; ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0, "timer delta: %M", delta); if (ngx_posted_accept_events) { ngx_event_process_posted(cycle, &ngx_posted_accept_events); } if (ngx_accept_mutex_held) { ngx_shmtx_unlock(&ngx_accept_mutex); } if (delta) { ngx_event_expire_timers(); } ngx_log_debug1(NGX_LOG_DEBUG_EVENT, cycle->log, 0, "posted events %p", ngx_posted_events); if (ngx_posted_events) { if (ngx_threaded) { ngx_wakeup_worker_thread(cycle); } else { ngx_event_process_posted(cycle, &ngx_posted_events); } } } ngx_int_t ngx_handle_read_event(ngx_event_t *rev, u_int flags) { if (ngx_event_flags & NGX_USE_CLEAR_EVENT) { /* kqueue, epoll */ if (!rev->active && !rev->ready) { if (ngx_add_event(rev, NGX_READ_EVENT, NGX_CLEAR_EVENT) == NGX_ERROR) { return NGX_ERROR; } } return NGX_OK; } else if (ngx_event_flags & NGX_USE_LEVEL_EVENT) { /* select, poll, /dev/poll */ if (!rev->active && !rev->ready) { if (ngx_add_event(rev, NGX_READ_EVENT, NGX_LEVEL_EVENT) == NGX_ERROR) { return NGX_ERROR; } return NGX_OK; } if (rev->active && (rev->ready || (flags & NGX_CLOSE_EVENT))) { if (ngx_del_event(rev, NGX_READ_EVENT, NGX_LEVEL_EVENT | flags) == NGX_ERROR) { return NGX_ERROR; } return NGX_OK; } } else if (ngx_event_flags & NGX_USE_ONESHOT_EVENT) { /* event ports */ if (!rev->active) { if (ngx_add_event(rev, NGX_READ_EVENT, NGX_ONESHOT_EVENT) == NGX_ERROR) { return NGX_ERROR; } } return NGX_OK; } /* aio, iocp, rtsig */ return NGX_OK; } ngx_int_t ngx_handle_write_event(ngx_event_t *wev, size_t lowat) { ngx_connection_t *c; if (lowat) { c = (ngx_connection_t *) wev->data; if (ngx_send_lowat(c, lowat) == NGX_ERROR) { return NGX_ERROR; } } if (ngx_event_flags & NGX_USE_CLEAR_EVENT) { /* kqueue, epoll */ if (!wev->active && !wev->ready) { if (ngx_add_event(wev, NGX_WRITE_EVENT, NGX_CLEAR_EVENT | (lowat ? NGX_LOWAT_EVENT : 0)) == NGX_ERROR) { return NGX_ERROR; } } return NGX_OK; } else if (ngx_event_flags & NGX_USE_LEVEL_EVENT) { /* select, poll, /dev/poll */ if (!wev->active && !wev->ready) { if (ngx_add_event(wev, NGX_WRITE_EVENT, NGX_LEVEL_EVENT) == NGX_ERROR) { return NGX_ERROR; } return NGX_OK; } if (wev->active && wev->ready) { if (ngx_del_event(wev, NGX_WRITE_EVENT, NGX_LEVEL_EVENT) == NGX_ERROR) { return NGX_ERROR; } return NGX_OK; } } else if (ngx_event_flags & NGX_USE_ONESHOT_EVENT) { /* event ports */ if (!wev->active) { if (ngx_add_event(wev, NGX_WRITE_EVENT, NGX_ONESHOT_EVENT) == NGX_ERROR) { return NGX_ERROR; } } return NGX_OK; } /* aio, iocp, rtsig */ return NGX_OK; } static ngx_int_t ngx_event_module_init(ngx_cycle_t *cycle) { void ***cf; u_char *shared; size_t size, cl; ngx_event_conf_t *ecf; ngx_core_conf_t *ccf; ngx_shm_t shm; #if !(NGX_WIN32) ngx_int_t limit; struct rlimit rlmt; #endif cf = ngx_get_conf(cycle->conf_ctx, ngx_events_module); if (cf == NULL) { ngx_log_error(NGX_LOG_EMERG, cycle->log, 0, "no \"events\" section in configuration"); return NGX_ERROR; } ecf = (*cf)[ngx_event_core_module.ctx_index]; if (!ngx_test_config) { ngx_log_error(NGX_LOG_NOTICE, cycle->log, 0, "using the \"%s\" event method", ecf->name); } ccf = (ngx_core_conf_t *) ngx_get_conf(cycle->conf_ctx, ngx_core_module); ngx_timer_resolution = ccf->timer_resolution; #if !(NGX_WIN32) if (getrlimit(RLIMIT_NOFILE, &rlmt) == -1) { ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno, "getrlimit(RLIMIT_NOFILE) failed, ignored"); } else { if (ecf->connections > (ngx_uint_t) rlmt.rlim_cur && (ccf->rlimit_nofile == NGX_CONF_UNSET || ecf->connections > (ngx_uint_t) ccf->rlimit_nofile)) { limit = (ccf->rlimit_nofile == NGX_CONF_UNSET) ? (ngx_int_t) rlmt.rlim_cur : ccf->rlimit_nofile; ngx_log_error(NGX_LOG_WARN, cycle->log, 0, "%ui worker_connections are more than " "open file resource limit: %i", ecf->connections, limit); } } #endif /* !(NGX_WIN32) */ if (ccf->master == 0) { return NGX_OK; } if (ngx_accept_mutex_ptr) { /* reinit ngx_accept_mutex */ if (ngx_shmtx_create(&ngx_accept_mutex, (void *) ngx_accept_mutex_ptr, ccf->lock_file.data, cycle->log) != NGX_OK) { return NGX_ERROR; } return NGX_OK; } /* cl should be equal or bigger than cache line size */ cl = 128; size = cl /* ngx_accept_mutex */ + cl; /* ngx_connection_counter */ #if (NGX_STAT_STUB) size += cl /* ngx_stat_accepted */ + cl /* ngx_stat_handled */ + cl /* ngx_stat_requests */ + cl /* ngx_stat_active */ + cl /* ngx_stat_reading */ + cl; /* ngx_stat_writing */ #endif shm.size = size; shm.log = cycle->log; if (ngx_shm_alloc(&shm) != NGX_OK) { return NGX_ERROR; } shared = shm.addr; ngx_accept_mutex_ptr = (ngx_atomic_t *) shared; if (ngx_shmtx_create(&ngx_accept_mutex, shared, ccf->lock_file.data, cycle->log) != NGX_OK) { return NGX_ERROR; } ngx_connection_counter = (ngx_atomic_t *) (shared + 1 * cl); #if (NGX_STAT_STUB) ngx_stat_accepted = (ngx_atomic_t *) (shared + 2 * cl); ngx_stat_handled = (ngx_atomic_t *) (shared + 3 * cl); ngx_stat_requests = (ngx_atomic_t *) (shared + 4 * cl); ngx_stat_active = (ngx_atomic_t *) (shared + 5 * cl); ngx_stat_reading = (ngx_atomic_t *) (shared + 6 * cl); ngx_stat_writing = (ngx_atomic_t *) (shared + 7 * cl); #endif *ngx_connection_counter = 1; ngx_log_debug2(NGX_LOG_DEBUG_EVENT, cycle->log, 0, "counter: %p, %d", ngx_connection_counter, *ngx_connection_counter); return NGX_OK; } #if !(NGX_WIN32) void ngx_timer_signal_handler(int signo) { ngx_event_timer_alarm = 1; ngx_time_update(0, 0); #if 1 ngx_log_debug0(NGX_LOG_DEBUG_EVENT, ngx_cycle->log, 0, "timer signal"); #endif } #endif static ngx_int_t ngx_event_process_init(ngx_cycle_t *cycle) { ngx_uint_t m, i; ngx_event_t *rev, *wev; ngx_listening_t *ls; ngx_connection_t *c, *next, *old; ngx_core_conf_t *ccf; ngx_event_conf_t *ecf; ngx_event_module_t *module; #if (NGX_WIN32) ngx_iocp_conf_t *iocpcf; #else struct rlimit rlmt; struct sigaction sa; struct itimerval itv; #endif ccf = (ngx_core_conf_t *) ngx_get_conf(cycle->conf_ctx, ngx_core_module); ecf = ngx_event_get_conf(cycle->conf_ctx, ngx_event_core_module); if (ccf->worker_processes > 1 && ecf->accept_mutex) { ngx_use_accept_mutex = 1; ngx_accept_mutex_held = 0; ngx_accept_mutex_delay = ecf->accept_mutex_delay; } else { ngx_use_accept_mutex = 0; } #if (NGX_THREADS) ngx_posted_events_mutex = ngx_mutex_init(cycle->log, 0); if (ngx_posted_events_mutex == NULL) { return NGX_ERROR; } #endif if (ngx_event_timer_init(cycle->log) == NGX_ERROR) { return NGX_ERROR; } cycle->connection_n = ecf->connections; for (m = 0; ngx_modules[m]; m++) { if (ngx_modules[m]->type != NGX_EVENT_MODULE) { continue; } if (ngx_modules[m]->ctx_index == ecf->use) { module = ngx_modules[m]->ctx; if (module->actions.init(cycle, ngx_timer_resolution) == NGX_ERROR) { /* fatal */ exit(2); } break; } } #if !(NGX_WIN32) if (ngx_timer_resolution && !(ngx_event_flags & NGX_USE_TIMER_EVENT)) { ngx_memzero(&sa, sizeof(struct sigaction)); sa.sa_handler = ngx_timer_signal_handler; sigemptyset(&sa.sa_mask); if (sigaction(SIGALRM, &sa, NULL) == -1) { ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno, "sigaction(SIGALRM) failed"); return NGX_ERROR; } itv.it_interval.tv_sec = ngx_timer_resolution / 1000; itv.it_interval.tv_usec = (ngx_timer_resolution % 1000) * 1000; itv.it_value.tv_sec = ngx_timer_resolution / 1000; itv.it_value.tv_usec = (ngx_timer_resolution % 1000 ) * 1000; if (setitimer(ITIMER_REAL, &itv, NULL) == -1) { ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno, "setitimer() failed"); } } if (ngx_event_flags & NGX_USE_FD_EVENT) { if (getrlimit(RLIMIT_NOFILE, &rlmt) == -1) { ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno, "getrlimit(RLIMIT_NOFILE) failed"); return NGX_ERROR; } cycle->files_n = (ngx_uint_t) rlmt.rlim_cur; cycle->files = ngx_calloc(sizeof(ngx_connection_t *) * cycle->files_n, cycle->log); if (cycle->files == NULL) { return NGX_ERROR; } } #endif cycle->connections = ngx_alloc(sizeof(ngx_connection_t) * ecf->connections, cycle->log); if (cycle->connections == NULL) { return NGX_ERROR; } c = cycle->connections; cycle->read_events = ngx_alloc(sizeof(ngx_event_t) * ecf->connections, cycle->log); if (cycle->read_events == NULL) { return NGX_ERROR; } rev = cycle->read_events; for (i = 0; i < cycle->connection_n; i++) { rev[i].closed = 1; rev[i].instance = 1; #if (NGX_THREADS) rev[i].lock = &c[i].lock; rev[i].own_lock = &c[i].lock; #endif } 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; #if (NGX_THREADS) wev[i].lock = &c[i].lock; wev[i].own_lock = &c[i].lock; #endif } i = cycle->connection_n; next = NULL; do { i--; c[i].data = next; c[i].read = &cycle->read_events[i]; c[i].write = &cycle->write_events[i]; c[i].fd = (ngx_socket_t) -1; next = &c[i]; #if (NGX_THREADS) c[i].lock = 0; #endif } while (i); cycle->free_connections = next; cycle->free_connection_n = ecf->connections; /* for each listening socket */ ls = cycle->listening.elts; for (i = 0; i < cycle->listening.nelts; i++) { c = ngx_get_connection(ls[i].fd, cycle->log); if (c == NULL) { return NGX_ERROR; } c->log = &ls[i].log; c->listening = &ls[i]; ls[i].connection = c; rev = c->read; rev->log = c->log; rev->accept = 1; #if (NGX_HAVE_DEFERRED_ACCEPT) rev->deferred_accept = ls[i].deferred_accept; #endif if (!(ngx_event_flags & NGX_USE_IOCP_EVENT)) { if (ls[i].previous) { /* * delete the old accept events that were bound to * the old cycle read events array */ old = ls[i].previous->connection; if (ngx_del_event(old->read, NGX_READ_EVENT, NGX_CLOSE_EVENT) == NGX_ERROR) { return NGX_ERROR; } old->fd = (ngx_socket_t) -1; } } #if (NGX_WIN32) if (ngx_event_flags & NGX_USE_IOCP_EVENT) { rev->handler = ngx_event_acceptex; if (ngx_add_event(rev, 0, NGX_IOCP_ACCEPT) == NGX_ERROR) { return NGX_ERROR; } ls[i].log.handler = ngx_acceptex_log_error; iocpcf = ngx_event_get_conf(cycle->conf_ctx, ngx_iocp_module); if (ngx_event_post_acceptex(&ls[i], iocpcf->post_acceptex) == NGX_ERROR) { return NGX_ERROR; } } else { rev->handler = ngx_event_accept; if (ngx_add_event(rev, NGX_READ_EVENT, 0) == NGX_ERROR) { return NGX_ERROR; } } #else rev->handler = ngx_event_accept; if (ngx_use_accept_mutex) { continue; } if (ngx_event_flags & NGX_USE_RTSIG_EVENT) { if (ngx_add_conn(c) == NGX_ERROR) { return NGX_ERROR; } } else { if (ngx_add_event(rev, NGX_READ_EVENT, 0) == NGX_ERROR) { return NGX_ERROR; } } #endif } return NGX_OK; } ngx_int_t ngx_send_lowat(ngx_connection_t *c, size_t lowat) { int sndlowat; #if (NGX_HAVE_LOWAT_EVENT) if (ngx_event_flags & NGX_USE_KQUEUE_EVENT) { c->write->available = lowat; return NGX_OK; } #endif if (lowat == 0 || c->sndlowat) { return NGX_OK; } sndlowat = (int) lowat; if (setsockopt(c->fd, SOL_SOCKET, SO_SNDLOWAT, (const void *) &sndlowat, sizeof(int)) == -1) { ngx_connection_error(c, ngx_socket_errno, "setsockopt(SO_SNDLOWAT) failed"); return NGX_ERROR; } c->sndlowat = 1; return NGX_OK; } static char * ngx_events_block(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) { char *rv; void ***ctx; ngx_uint_t i; ngx_conf_t pcf; ngx_event_module_t *m; /* count the number of the event modules and set up their indices */ ngx_event_max_module = 0; for (i = 0; ngx_modules[i]; i++) { if (ngx_modules[i]->type != NGX_EVENT_MODULE) { continue; } ngx_modules[i]->ctx_index = ngx_event_max_module++; } ctx = ngx_pcalloc(cf->pool, sizeof(void *)); if (ctx == NULL) { return NGX_CONF_ERROR; } *ctx = ngx_pcalloc(cf->pool, ngx_event_max_module * sizeof(void *)); if (*ctx == NULL) { return NGX_CONF_ERROR; } *(void **) conf = ctx; for (i = 0; ngx_modules[i]; i++) { if (ngx_modules[i]->type != NGX_EVENT_MODULE) { continue; } m = ngx_modules[i]->ctx; if (m->create_conf) { (*ctx)[ngx_modules[i]->ctx_index] = m->create_conf(cf->cycle); if ((*ctx)[ngx_modules[i]->ctx_index] == NULL) { return NGX_CONF_ERROR; } } } pcf = *cf; cf->ctx = ctx; cf->module_type = NGX_EVENT_MODULE; cf->cmd_type = NGX_EVENT_CONF; rv = ngx_conf_parse(cf, NULL); *cf = pcf; if (rv != NGX_CONF_OK) return rv; for (i = 0; ngx_modules[i]; i++) { if (ngx_modules[i]->type != NGX_EVENT_MODULE) { continue; } m = ngx_modules[i]->ctx; if (m->init_conf) { rv = m->init_conf(cf->cycle, (*ctx)[ngx_modules[i]->ctx_index]); if (rv != NGX_CONF_OK) { return rv; } } } return NGX_CONF_OK; } static char * ngx_event_connections(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) { ngx_event_conf_t *ecf = conf; ngx_str_t *value; if (ecf->connections != NGX_CONF_UNSET_UINT) { return "is duplicate" ; } if (ngx_strcmp(cmd->name.data, "connections") == 0) { ngx_conf_log_error(NGX_LOG_WARN, cf, 0, "the \"connections\" directive is deprecated, " "use the \"worker_connections\" directive instead"); } value = cf->args->elts; ecf->connections = ngx_atoi(value[1].data, value[1].len); if (ecf->connections == (ngx_uint_t) NGX_ERROR) { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "invalid number \"%V\"", &value[1]); return NGX_CONF_ERROR; } cf->cycle->connection_n = ecf->connections; return NGX_CONF_OK; } static char * ngx_event_use(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) { ngx_event_conf_t *ecf = conf; ngx_int_t m; ngx_str_t *value; ngx_event_conf_t *old_ecf; ngx_event_module_t *module; if (ecf->use != NGX_CONF_UNSET_UINT) { return "is duplicate" ; } value = cf->args->elts; if (cf->cycle->old_cycle->conf_ctx) { old_ecf = ngx_event_get_conf(cf->cycle->old_cycle->conf_ctx, ngx_event_core_module); } else { old_ecf = NULL; } for (m = 0; ngx_modules[m]; m++) { if (ngx_modules[m]->type != NGX_EVENT_MODULE) { continue; } module = ngx_modules[m]->ctx; if (module->name->len == value[1].len) { if (ngx_strcmp(module->name->data, value[1].data) == 0) { ecf->use = ngx_modules[m]->ctx_index; ecf->name = module->name->data; if (ngx_process == NGX_PROCESS_SINGLE && old_ecf && old_ecf->use != ecf->use) { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "when the server runs without a master process " "the \"%V\" event type must be the same as " "in previous configuration - \"%s\" " "and it can not be changed on the fly, " "to change it you need to stop server " "and start it again", &value[1], old_ecf->name); return NGX_CONF_ERROR; } return NGX_CONF_OK; } } } ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "invalid event type \"%V\"", &value[1]); return NGX_CONF_ERROR; } static char * ngx_event_debug_connection(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) { #if (NGX_DEBUG) ngx_event_conf_t *ecf = conf; in_addr_t *addr; ngx_str_t *value; struct hostent *h; value = cf->args->elts; /* AF_INET only */ addr = ngx_array_push(&ecf->debug_connection); if (addr == NULL) { return NGX_CONF_ERROR; } *addr = inet_addr((char *) value[1].data); if (*addr != INADDR_NONE) { return NGX_OK; } h = gethostbyname((char *) value[1].data); if (h == NULL || h->h_addr_list[0] == NULL) { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "host \"%s\" not found", value[1].data); return NGX_CONF_ERROR; } *addr = *(in_addr_t *)(h->h_addr_list[0]); #else ngx_conf_log_error(NGX_LOG_WARN, cf, 0, "\"debug_connection\" is ignored, you need to rebuild " "nginx using --with-debug option to enable it"); #endif return NGX_OK; } static void * ngx_event_create_conf(ngx_cycle_t *cycle) { ngx_event_conf_t *ecf; ecf = ngx_palloc(cycle->pool, sizeof(ngx_event_conf_t)); if (ecf == NULL) { return NGX_CONF_ERROR; } ecf->connections = NGX_CONF_UNSET_UINT; ecf->use = NGX_CONF_UNSET_UINT; ecf->multi_accept = NGX_CONF_UNSET; ecf->accept_mutex = NGX_CONF_UNSET; ecf->accept_mutex_delay = NGX_CONF_UNSET_MSEC; ecf->name = (void *) NGX_CONF_UNSET; #if (NGX_DEBUG) if (ngx_array_init(&ecf->debug_connection, cycle->pool, 4, sizeof(in_addr_t)) == NGX_ERROR) { return NGX_CONF_ERROR; } #endif return ecf; } static char * ngx_event_init_conf(ngx_cycle_t *cycle, void *conf) { ngx_event_conf_t *ecf = conf; #if (NGX_HAVE_EPOLL) && !(NGX_TEST_BUILD_EPOLL) int fd; #endif #if (NGX_HAVE_RTSIG) ngx_uint_t rtsig; ngx_core_conf_t *ccf; #endif ngx_int_t i, connections; ngx_module_t *module; ngx_event_module_t *event_module; connections = NGX_CONF_UNSET_UINT; module = NULL; #if (NGX_HAVE_EPOLL) && !(NGX_TEST_BUILD_EPOLL) fd = epoll_create(100); if (fd != -1) { close(fd); connections = DEFAULT_CONNECTIONS; module = &ngx_epoll_module; } else if (ngx_errno != NGX_ENOSYS) { connections = DEFAULT_CONNECTIONS; module = &ngx_epoll_module; } #endif #if (NGX_HAVE_RTSIG) if (module == NULL) { connections = DEFAULT_CONNECTIONS; module = &ngx_rtsig_module; rtsig = 1; } else { rtsig = 0; } #endif #if (NGX_HAVE_DEVPOLL) connections = DEFAULT_CONNECTIONS; module = &ngx_devpoll_module; #endif #if (NGX_HAVE_KQUEUE) connections = DEFAULT_CONNECTIONS; module = &ngx_kqueue_module; #endif #if (NGX_HAVE_SELECT) if (module == NULL) { #if (NGX_WIN32 || FD_SETSIZE >= DEFAULT_CONNECTIONS) connections = DEFAULT_CONNECTIONS; #else connections = FD_SETSIZE; #endif module = &ngx_select_module; } #endif if (module == NULL) { for (i = 0; ngx_modules[i]; i++) { if (ngx_modules[i]->type == NGX_EVENT_MODULE) { event_module = ngx_modules[i]->ctx; if (ngx_strcmp(event_module->name->data, event_core_name.data) == 0) { continue; } module = ngx_modules[i]; break; } } } if (module == NULL) { ngx_log_error(NGX_LOG_EMERG, cycle->log, 0, "no events module found"); return NGX_CONF_ERROR; } ngx_conf_init_unsigned_value(ecf->connections, connections); cycle->connection_n = ecf->connections; ngx_conf_init_unsigned_value(ecf->use, module->ctx_index); event_module = module->ctx; ngx_conf_init_ptr_value(ecf->name, event_module->name->data); ngx_conf_init_value(ecf->multi_accept, 0); ngx_conf_init_value(ecf->accept_mutex, 1); ngx_conf_init_msec_value(ecf->accept_mutex_delay, 500); #if (NGX_HAVE_RTSIG) if (!rtsig) { return NGX_CONF_OK; } if (ecf->accept_mutex) { return NGX_CONF_OK; } ccf = (ngx_core_conf_t *) ngx_get_conf(cycle->conf_ctx, ngx_core_module); if (ccf->worker_processes == 0) { return NGX_CONF_OK; } ngx_log_error(NGX_LOG_EMERG, cycle->log, 0, "the \"rtsig\" method requires \"accept_mutex\" to be on"); return NGX_CONF_ERROR; #else return NGX_CONF_OK; #endif }