From c2068d08f097383b8eac508117e6d405627e6cef Mon Sep 17 00:00:00 2001 From: Igor Sysoev Date: Wed, 19 Oct 2005 12:33:58 +0000 Subject: nginx-0.3.3-RELEASE import *) Change: the "bl" and "af" parameters of the "listen" directive was renamed to the "backlog" and "accept_filter". *) Feature: the "rcvbuf" and "sndbuf" parameters of the "listen" directive. *) Change: the "$msec" log parameter does not require now the additional the gettimeofday() system call. *) Feature: the -t switch now tests the "listen" directives. *) Bugfix: if the invalid address was specified in the "listen" directive, then after the -HUP signal nginx left an open socket in the CLOSED state. *) Bugfix: the mime type may be incorrectly set to default value for index file with variable in the name; the bug had appeared in 0.3.0. *) Feature: the "timer_resolution" directive. *) Feature: the millisecond "$upstream_response_time" log parameter. *) Bugfix: a temporary file with client request body now is removed just after the response header was transferred to a client. *) Bugfix: OpenSSL 0.9.6 compatibility. *) Bugfix: the SSL certificate and key file paths could not be relative. *) Bugfix: the "ssl_prefer_server_ciphers" directive did not work in the ngx_imap_ssl_module. *) Bugfix: the "ssl_protocols" directive allowed to specify the single protocol only. --- src/core/nginx.c | 15 ++- src/core/nginx.h | 2 +- src/core/ngx_conf_file.c | 2 +- src/core/ngx_config.h | 3 + src/core/ngx_connection.c | 281 ++++++++++++++++++++++++++++++++++++---------- src/core/ngx_connection.h | 6 +- src/core/ngx_cycle.c | 135 +++------------------- src/core/ngx_cycle.h | 2 + src/core/ngx_file.c | 25 ++--- src/core/ngx_palloc.c | 20 +++- src/core/ngx_palloc.h | 3 +- src/core/ngx_parse.c | 11 +- src/core/ngx_parse.h | 2 +- src/core/ngx_radix_tree.c | 15 ++- src/core/ngx_spinlock.c | 3 +- src/core/ngx_times.c | 191 +++++++++++-------------------- src/core/ngx_times.h | 36 +++--- 17 files changed, 393 insertions(+), 359 deletions(-) (limited to 'src/core') diff --git a/src/core/nginx.c b/src/core/nginx.c index cc13f75c1..e08ca165b 100644 --- a/src/core/nginx.c +++ b/src/core/nginx.c @@ -29,19 +29,26 @@ static ngx_conf_enum_t ngx_debug_points[] = { static ngx_command_t ngx_core_commands[] = { { ngx_string("daemon"), - NGX_MAIN_CONF|NGX_DIRECT_CONF|NGX_CONF_TAKE1, + NGX_MAIN_CONF|NGX_DIRECT_CONF|NGX_CONF_FLAG, ngx_conf_set_flag_slot, 0, offsetof(ngx_core_conf_t, daemon), NULL }, { ngx_string("master_process"), - NGX_MAIN_CONF|NGX_DIRECT_CONF|NGX_CONF_TAKE1, + NGX_MAIN_CONF|NGX_DIRECT_CONF|NGX_CONF_FLAG, ngx_conf_set_flag_slot, 0, offsetof(ngx_core_conf_t, master), NULL }, + { ngx_string("timer_resolution"), + NGX_MAIN_CONF|NGX_DIRECT_CONF|NGX_CONF_TAKE1, + ngx_conf_set_msec_slot, + 0, + offsetof(ngx_core_conf_t, timer_resolution), + NULL }, + { ngx_string("pid"), NGX_MAIN_CONF|NGX_DIRECT_CONF|NGX_CONF_TAKE1, ngx_conf_set_str_slot, @@ -534,6 +541,8 @@ ngx_core_module_create_conf(ngx_cycle_t *cycle) ccf->daemon = NGX_CONF_UNSET; ccf->master = NGX_CONF_UNSET; + ccf->timer_resolution = NGX_CONF_UNSET_MSEC; + ccf->worker_processes = NGX_CONF_UNSET; ccf->debug_points = NGX_CONF_UNSET; @@ -564,6 +573,8 @@ ngx_core_module_init_conf(ngx_cycle_t *cycle, void *conf) ngx_conf_init_value(ccf->daemon, 1); ngx_conf_init_value(ccf->master, 1); + ngx_conf_init_msec_value(ccf->timer_resolution, 0); + ngx_conf_init_value(ccf->worker_processes, 1); ngx_conf_init_value(ccf->debug_points, 0); diff --git a/src/core/nginx.h b/src/core/nginx.h index 67e8e6b02..e482c424f 100644 --- a/src/core/nginx.h +++ b/src/core/nginx.h @@ -8,7 +8,7 @@ #define _NGINX_H_INCLUDED_ -#define NGINX_VER "nginx/0.3.2" +#define NGINX_VER "nginx/0.3.3" #define NGINX_VAR "NGINX" #define NGX_OLDPID_EXT ".oldbin" diff --git a/src/core/ngx_conf_file.c b/src/core/ngx_conf_file.c index 0e671ef3a..78e61f8c1 100644 --- a/src/core/ngx_conf_file.c +++ b/src/core/ngx_conf_file.c @@ -624,7 +624,7 @@ ngx_conf_include(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) value = cf->args->elts; file = value[1]; - if (ngx_conf_full_name(cf->cycle, &file) == NGX_ERROR){ + if (ngx_conf_full_name(cf->cycle, &file) == NGX_ERROR) { return NGX_CONF_ERROR; } diff --git a/src/core/ngx_config.h b/src/core/ngx_config.h index 7c5687e1b..3b51e9622 100644 --- a/src/core/ngx_config.h +++ b/src/core/ngx_config.h @@ -104,6 +104,9 @@ typedef long ngx_flag_t; #define ngx_align(p) (u_char *) (((uintptr_t) p + NGX_ALIGN) & ~NGX_ALIGN) +#define ngx_abort abort + + /* TODO: auto_conf: ngx_inline inline __inline __inline__ */ #ifndef ngx_inline #define ngx_inline inline diff --git a/src/core/ngx_connection.c b/src/core/ngx_connection.c index 3f36d3155..cac394400 100644 --- a/src/core/ngx_connection.c +++ b/src/core/ngx_connection.c @@ -66,13 +66,12 @@ ngx_set_inherited_sockets(ngx_cycle_t *cycle) ngx_uint_t i; ngx_listening_t *ls; struct sockaddr_in *sin; + socklen_t olen; #if (NGX_HAVE_DEFERRED_ACCEPT && defined SO_ACCEPTFILTER) ngx_err_t err; - socklen_t aflen; struct accept_filter_arg af; #endif #if (NGX_HAVE_DEFERRED_ACCEPT && defined TCP_DEFER_ACCEPT) - socklen_t tlen; int timeout; #endif @@ -126,12 +125,38 @@ ngx_set_inherited_sockets(ngx_cycle_t *cycle) ls[i].backlog = -1; + olen = sizeof(int); + + if (getsockopt(ls[i].fd, SOL_SOCKET, SO_RCVBUF, (void *) &ls[i].rcvbuf, + &olen) + == -1) + { + ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_socket_errno, + "getsockopt(SO_RCVBUF) %V failed, ignored", + &ls[i].addr_text); + + ls[i].rcvbuf = -1; + } + + olen = sizeof(int); + + if (getsockopt(ls[i].fd, SOL_SOCKET, SO_SNDBUF, (void *) &ls[i].sndbuf, + &olen) + == -1) + { + ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_socket_errno, + "getsockopt(SO_SNDBUF) %V failed, ignored", + &ls[i].addr_text); + + ls[i].sndbuf = -1; + } + #if (NGX_HAVE_DEFERRED_ACCEPT && defined SO_ACCEPTFILTER) ngx_memzero(&af, sizeof(struct accept_filter_arg)); - aflen = sizeof(struct accept_filter_arg); + olen = sizeof(struct accept_filter_arg); - if (getsockopt(ls[i].fd, SOL_SOCKET, SO_ACCEPTFILTER, &af, &aflen) + if (getsockopt(ls[i].fd, SOL_SOCKET, SO_ACCEPTFILTER, &af, &olen) == -1) { err = ngx_errno; @@ -146,7 +171,7 @@ ngx_set_inherited_sockets(ngx_cycle_t *cycle) continue; } - if (aflen < sizeof(struct accept_filter_arg) || af.af_name[0] == '\0') { + if (olen < sizeof(struct accept_filter_arg) || af.af_name[0] == '\0') { continue; } @@ -162,9 +187,9 @@ ngx_set_inherited_sockets(ngx_cycle_t *cycle) #if (NGX_HAVE_DEFERRED_ACCEPT && defined TCP_DEFER_ACCEPT) timeout = 0; - tlen = sizeof(int); + olen = sizeof(int); - if (getsockopt(ls[i].fd, IPPROTO_TCP, TCP_DEFER_ACCEPT, &timeout, &tlen) + if (getsockopt(ls[i].fd, IPPROTO_TCP, TCP_DEFER_ACCEPT, &timeout, &olen) == -1) { ngx_log_error(NGX_LOG_NOTICE, cycle->log, ngx_errno, @@ -188,7 +213,8 @@ ngx_set_inherited_sockets(ngx_cycle_t *cycle) ngx_int_t ngx_open_listening_sockets(ngx_cycle_t *cycle) { - ngx_uint_t tries, failed, reuseaddr, i; + int reuseaddr; + ngx_uint_t i, tries, failed; ngx_err_t err; ngx_log_t *log; ngx_socket_t s; @@ -201,9 +227,9 @@ ngx_open_listening_sockets(ngx_cycle_t *cycle) log = cycle->log; - /* TODO: tries configurable */ + /* TODO: configurable try number */ - for (tries = /* STUB */ 5; tries; tries--) { + for (tries = 5 ; tries; tries--) { failed = 0; /* for each listening socket */ @@ -236,25 +262,19 @@ ngx_open_listening_sockets(ngx_cycle_t *cycle) return NGX_ERROR; } -#if (NGX_WIN32) - - /* - * Winsock assignes a socket number divisible by 4 - * so to find a connection we divide a socket number by 4. - */ - - if (s % 4) { - ngx_log_error(NGX_LOG_EMERG, log, 0, - ngx_socket_n " created socket %d", s); - return NGX_ERROR; - } -#endif - if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, - (const void *) &reuseaddr, sizeof(int)) == -1) { + (const void *) &reuseaddr, sizeof(int)) + == -1) + { ngx_log_error(NGX_LOG_EMERG, log, ngx_socket_errno, "setsockopt(SO_REUSEADDR) %V failed", &ls[i].addr_text); + + if (ngx_close_socket(s) == -1) + ngx_log_error(NGX_LOG_EMERG, log, ngx_socket_errno, + ngx_close_socket_n " %V failed", + &ls[i].addr_text); + return NGX_ERROR; } @@ -265,56 +285,54 @@ ngx_open_listening_sockets(ngx_cycle_t *cycle) ngx_log_error(NGX_LOG_EMERG, log, ngx_socket_errno, ngx_nonblocking_n " %V failed", &ls[i].addr_text); - return NGX_ERROR; - } - } -#if 0 - if (ls[i].nonblocking) { - if (ngx_nonblocking(s) == -1) { - ngx_log_error(NGX_LOG_EMERG, log, ngx_socket_errno, - ngx_nonblocking_n " %V failed", - &ls[i].addr_text); + if (ngx_close_socket(s) == -1) + ngx_log_error(NGX_LOG_EMERG, log, ngx_socket_errno, + ngx_close_socket_n " %V failed", + &ls[i].addr_text); + return NGX_ERROR; } } -#endif if (bind(s, ls[i].sockaddr, ls[i].socklen) == -1) { err = ngx_socket_errno; + + if (err == NGX_EADDRINUSE && ngx_test_config) { + continue; + } + ngx_log_error(NGX_LOG_EMERG, log, err, "bind() to %V failed", &ls[i].addr_text); - if (err != NGX_EADDRINUSE) - return NGX_ERROR; - if (ngx_close_socket(s) == -1) ngx_log_error(NGX_LOG_EMERG, log, ngx_socket_errno, ngx_close_socket_n " %V failed", &ls[i].addr_text); + if (err != NGX_EADDRINUSE) { + return NGX_ERROR; + } + failed = 1; - continue; - } - if (listen(s, ls[i].backlog) == -1) { - ngx_log_error(NGX_LOG_EMERG, log, ngx_socket_errno, - "listen() to %V failed", &ls[i].addr_text); - return NGX_ERROR; + continue; } - /* TODO: deferred accept */ + ls[i].listen = 1; ls[i].fd = s; } - if (!failed) + if (!failed) { break; + } /* TODO: delay configurable */ ngx_log_error(NGX_LOG_NOTICE, log, 0, "try again to bind() after 500ms"); + ngx_msleep(500); } @@ -327,6 +345,143 @@ ngx_open_listening_sockets(ngx_cycle_t *cycle) } +void +ngx_configure_listening_socket(ngx_cycle_t *cycle) +{ + ngx_uint_t i; + ngx_listening_t *ls; + +#if (NGX_HAVE_DEFERRED_ACCEPT && defined SO_ACCEPTFILTER) + struct accept_filter_arg af; +#endif +#if (NGX_HAVE_DEFERRED_ACCEPT && defined TCP_DEFER_ACCEPT) + int timeout; +#endif + + ls = cycle->listening.elts; + for (i = 0; i < cycle->listening.nelts; i++) { + + if (ls[i].rcvbuf != -1) { + if (setsockopt(ls[i].fd, SOL_SOCKET, SO_RCVBUF, + (const void *) &ls[i].rcvbuf, sizeof(int)) + == -1) + { + ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_socket_errno, + "setsockopt(SO_RCVBUF) %V failed, ignored", + &ls[i].addr_text); + return; + } + } + + if (ls[i].sndbuf != -1) { + if (setsockopt(ls[i].fd, SOL_SOCKET, SO_SNDBUF, + (const void *) &ls[i].sndbuf, sizeof(int)) + == -1) + { + ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_socket_errno, + "setsockopt(SO_SNDBUF) %V failed, ignored", + &ls[i].addr_text); + return; + } + } + + if (ls[i].listen) { + if (listen(ls[i].fd, ls[i].backlog) == -1) { + ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_socket_errno, + "changing the listen() backlog to %d " + "for %V failed, ignored", + &ls[i].addr_text, ls[i].backlog); + } + } + + /* + * setting deferred mode should be last operation on socket, + * because code may prematurely continue cycle on failure + */ + +#if (NGX_HAVE_DEFERRED_ACCEPT) + +#ifdef SO_ACCEPTFILTER + + if (ls->delete_deferred) { + if (setsockopt(ls->fd, SOL_SOCKET, SO_ACCEPTFILTER, NULL, 0) == -1) + { + ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno, + "setsockopt(SO_ACCEPTFILTER, NULL) " + "for %V failed, ignored", + &ls->addr_text); + + if (ls->accept_filter) { + ngx_log_error(NGX_LOG_ALERT, cycle->log, 0, + "could not change the accept filter " + "to \"%s\" for %V, ignored", + ls->accept_filter, &ls->addr_text); + } + + continue; + } + + ls->deferred_accept = 0; + } + + if (ls->add_deferred) { + ngx_memzero(&af, sizeof(struct accept_filter_arg)); + (void) ngx_cpystrn((u_char *) af.af_name, + (u_char *) ls->accept_filter, 16); + + if (setsockopt(ls->fd, SOL_SOCKET, SO_ACCEPTFILTER, + &af, sizeof(struct accept_filter_arg)) + == -1) + { + ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno, + "setsockopt(SO_ACCEPTFILTER, \"%s\") " + " for %V failed, ignored", + ls->accept_filter, &ls->addr_text); + continue; + } + + ls->deferred_accept = 1; + } + +#endif + +#ifdef TCP_DEFER_ACCEPT + + if (ls->add_deferred || ls->delete_deferred) { + + if (ls->add_deferred) { + timeout = (int) (ls->post_accept_timeout / 1000); + + } else { + timeout = 0; + } + + if (setsockopt(ls->fd, IPPROTO_TCP, TCP_DEFER_ACCEPT, + &timeout, sizeof(int)) + == -1) + { + ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno, + "setsockopt(TCP_DEFER_ACCEPT, %d) for %V failed, " + "ignored", + timeout, &ls->addr_text); + + continue; + } + } + + if (ls->add_deferred) { + ls->deferred_accept = 1; + } + +#endif + +#endif /* NGX_HAVE_DEFERRED_ACCEPT */ + } + + return; +} + + void ngx_close_listening_sockets(ngx_cycle_t *cycle) { @@ -361,6 +516,9 @@ ngx_close_listening_sockets(ngx_cycle_t *cycle) c->fd = (ngx_socket_t) -1; + ngx_log_debug2(NGX_LOG_DEBUG_CORE, cycle->log, 0, + "close listening %V #%d ", &ls[i].addr_text, ls[i].fd); + if (ngx_close_socket(ls[i].fd) == -1) { ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_socket_errno, ngx_close_socket_n " %V failed", &ls[i].addr_text); @@ -495,28 +653,27 @@ ngx_close_connection(ngx_connection_t *c) * before we clean the connection */ - if (ngx_mutex_lock(ngx_posted_events_mutex) == NGX_OK) { - - if (c->read->prev) { - ngx_delete_posted_event(c->read); - } + ngx_mutex_lock(ngx_posted_events_mutex); - if (c->write->prev) { - ngx_delete_posted_event(c->write); - } + if (c->read->prev) { + ngx_delete_posted_event(c->read); + } - c->read->closed = 1; - c->write->closed = 1; + if (c->write->prev) { + ngx_delete_posted_event(c->write); + } - if (c->single_connection) { - ngx_unlock(&c->lock); - c->read->locked = 0; - c->write->locked = 0; - } + c->read->closed = 1; + c->write->closed = 1; - ngx_mutex_unlock(ngx_posted_events_mutex); + 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) { diff --git a/src/core/ngx_connection.h b/src/core/ngx_connection.h index ca5b05325..c2b77e043 100644 --- a/src/core/ngx_connection.h +++ b/src/core/ngx_connection.h @@ -25,7 +25,10 @@ struct ngx_listening_s { int family; int type; + int backlog; + int rcvbuf; + int sndbuf; /* handler of accepted connection */ ngx_connection_handler_pt handler; @@ -51,7 +54,7 @@ struct ngx_listening_s { unsigned bound:1; /* already bound */ unsigned inherited:1; /* inherited from previous process */ unsigned nonblocking_accept:1; - unsigned change_backlog:1; + unsigned listen:1; unsigned nonblocking:1; unsigned shared:1; /* shared between threads or processes */ unsigned addr_ntop:1; @@ -162,6 +165,7 @@ ngx_listening_t *ngx_listening_inet_stream_socket(ngx_conf_t *cf, in_addr_t addr, in_port_t port); ngx_int_t ngx_set_inherited_sockets(ngx_cycle_t *cycle); ngx_int_t ngx_open_listening_sockets(ngx_cycle_t *cycle); +void ngx_configure_listening_socket(ngx_cycle_t *cycle); void ngx_close_listening_sockets(ngx_cycle_t *cycle); void ngx_close_connection(ngx_connection_t *c); ngx_int_t ngx_connection_error(ngx_connection_t *c, ngx_err_t err, char *text); diff --git a/src/core/ngx_cycle.c b/src/core/ngx_cycle.c index d8f95fa4d..58679ed28 100644 --- a/src/core/ngx_cycle.c +++ b/src/core/ngx_cycle.c @@ -37,7 +37,8 @@ static ngx_str_t error_log = ngx_null_string; #endif -ngx_cycle_t *ngx_init_cycle(ngx_cycle_t *old_cycle) +ngx_cycle_t * +ngx_init_cycle(ngx_cycle_t *old_cycle) { void *rv; ngx_uint_t i, n, failed; @@ -45,18 +46,11 @@ ngx_cycle_t *ngx_init_cycle(ngx_cycle_t *old_cycle) ngx_conf_t conf; ngx_pool_t *pool; ngx_cycle_t *cycle, **old; - ngx_socket_t fd; ngx_list_part_t *part; ngx_open_file_t *file; ngx_listening_t *ls, *nls; ngx_core_conf_t *ccf; ngx_core_module_t *module; -#if (NGX_HAVE_DEFERRED_ACCEPT && defined SO_ACCEPTFILTER) - struct accept_filter_arg af; -#endif -#if (NGX_HAVE_DEFERRED_ACCEPT && defined TCP_DEFER_ACCEPT) - int timeout; -#endif log = old_cycle->log; @@ -315,39 +309,19 @@ ngx_cycle_t *ngx_init_cycle(ngx_cycle_t *old_cycle) if (ngx_cmp_sockaddr(nls[n].sockaddr, ls[i].sockaddr) == NGX_OK) { - fd = ls[i].fd; -#if (NGX_WIN32) - /* - * Winsock assignes a socket number divisible by 4 so - * to find a connection we divide a socket number by 4. - */ - - fd /= 4; -#endif - if (fd >= (ngx_socket_t) cycle->connection_n) { - ngx_log_error(NGX_LOG_EMERG, log, 0, - "%d connections is not enough to hold " - "an open listening socket on %V, " - "required at least %d connections", - cycle->connection_n, - &ls[i].addr_text, fd); - failed = 1; - break; - } - nls[n].fd = ls[i].fd; nls[n].previous = &ls[i]; ls[i].remain = 1; if (ls[n].backlog != nls[i].backlog) { - nls[n].change_backlog = 1; + nls[n].listen = 1; } #if (NGX_HAVE_DEFERRED_ACCEPT && defined SO_ACCEPTFILTER) /* * FreeBSD, except the most recent versions, - * can not remove accept filter + * could not remove accept filter */ nls[n].deferred_accept = ls[i].deferred_accept; @@ -404,93 +378,13 @@ ngx_cycle_t *ngx_init_cycle(ngx_cycle_t *old_cycle) } } - if (!ngx_test_config && !failed) { + if (!failed) { if (ngx_open_listening_sockets(cycle) == NGX_ERROR) { failed = 1; } - if (!failed) { - ls = cycle->listening.elts; - for (i = 0; i < cycle->listening.nelts; i++) { - - if (ls[i].change_backlog) { - if (listen(ls[i].fd, ls[i].backlog) == -1) { - ngx_log_error(NGX_LOG_ALERT, log, ngx_socket_errno, - "changing the listen() backlog to %d " - "for %V failed, ignored", - &ls[i].addr_text, ls[i].backlog); - } - } - -#if (NGX_HAVE_DEFERRED_ACCEPT) - -#ifdef SO_ACCEPTFILTER - if (ls[i].delete_deferred) { - if (setsockopt(ls[i].fd, SOL_SOCKET, SO_ACCEPTFILTER, - NULL, 0) == -1) - { - ngx_log_error(NGX_LOG_ALERT, log, ngx_errno, - "setsockopt(SO_ACCEPTFILTER, NULL) " - "for %V failed, ignored", - &ls[i].addr_text); - - if (ls[i].accept_filter) { - ngx_log_error(NGX_LOG_ALERT, log, 0, - "could not change the accept filter " - "to \"%s\" for %V, ignored", - ls[i].accept_filter, &ls[i].addr_text); - } - - continue; - } - - ls[i].deferred_accept = 0; - } - - if (ls[i].add_deferred) { - ngx_memzero(&af, sizeof(struct accept_filter_arg)); - (void) ngx_cpystrn((u_char *) af.af_name, - (u_char *) ls[i].accept_filter, 16); - - if (setsockopt(ls[i].fd, SOL_SOCKET, SO_ACCEPTFILTER, - &af, sizeof(struct accept_filter_arg)) == -1) - { - ngx_log_error(NGX_LOG_ALERT, log, ngx_errno, - "setsockopt(SO_ACCEPTFILTER, \"%s\") " - "for %V failed, ignored", - ls[i].accept_filter, &ls[i].addr_text); - continue; - } - - ls[i].deferred_accept = 1; - } -#endif - -#ifdef TCP_DEFER_ACCEPT - if (ls[i].add_deferred || ls[i].delete_deferred) { - timeout = 0; - - if (ls[i].add_deferred) { - timeout = (int) (ls[i].post_accept_timeout / 1000); - } - - if (setsockopt(ls[i].fd, IPPROTO_TCP, TCP_DEFER_ACCEPT, - &timeout, sizeof(int)) == -1) - { - ngx_log_error(NGX_LOG_ALERT, log, ngx_errno, - "setsockopt(TCP_DEFER_ACCEPT, %d) " - "for %V failed, ignored", - timeout, &ls[i].addr_text); - continue; - } - } - - if (ls[i].add_deferred) { - ls[i].deferred_accept = 1; - } -#endif -#endif - } + if (!ngx_test_config && !failed) { + ngx_configure_listening_socket(cycle); } } } @@ -680,7 +574,8 @@ ngx_cycle_t *ngx_init_cycle(ngx_cycle_t *old_cycle) } -static ngx_int_t ngx_cmp_sockaddr(struct sockaddr *sa1, struct sockaddr *sa2) +static ngx_int_t +ngx_cmp_sockaddr(struct sockaddr *sa1, struct sockaddr *sa2) { struct sockaddr_in *sin1, *sin2; @@ -707,7 +602,8 @@ static ngx_int_t ngx_cmp_sockaddr(struct sockaddr *sa1, struct sockaddr *sa2) #if !(NGX_WIN32) -ngx_int_t ngx_create_pidfile(ngx_cycle_t *cycle, ngx_cycle_t *old_cycle) +ngx_int_t +ngx_create_pidfile(ngx_cycle_t *cycle, ngx_cycle_t *old_cycle) { ngx_uint_t trunc; size_t len; @@ -776,7 +672,8 @@ ngx_int_t ngx_create_pidfile(ngx_cycle_t *cycle, ngx_cycle_t *old_cycle) } -void ngx_delete_pidfile(ngx_cycle_t *cycle) +void +ngx_delete_pidfile(ngx_cycle_t *cycle) { u_char *name; ngx_core_conf_t *ccf; @@ -798,7 +695,8 @@ void ngx_delete_pidfile(ngx_cycle_t *cycle) #endif -void ngx_reopen_files(ngx_cycle_t *cycle, ngx_uid_t user) +void +ngx_reopen_files(ngx_cycle_t *cycle, ngx_uid_t user) { ngx_fd_t fd; ngx_uint_t i; @@ -936,7 +834,8 @@ void ngx_reopen_files(ngx_cycle_t *cycle, ngx_uid_t user) } -static void ngx_clean_old_cycles(ngx_event_t *ev) +static void +ngx_clean_old_cycles(ngx_event_t *ev) { ngx_uint_t i, n, found, live; ngx_log_t *log; diff --git a/src/core/ngx_cycle.h b/src/core/ngx_cycle.h index a94444a91..b297994ea 100644 --- a/src/core/ngx_cycle.h +++ b/src/core/ngx_cycle.h @@ -54,6 +54,8 @@ typedef struct { ngx_flag_t daemon; ngx_flag_t master; + ngx_msec_t timer_resolution; + ngx_int_t worker_processes; ngx_int_t debug_points; diff --git a/src/core/ngx_file.c b/src/core/ngx_file.c index 76e71c748..0c6576087 100644 --- a/src/core/ngx_file.c +++ b/src/core/ngx_file.c @@ -40,8 +40,8 @@ ngx_create_temp_file(ngx_file_t *file, ngx_path_t *path, ngx_pool_t *pool, { ngx_err_t err; ngx_atomic_uint_t n; - ngx_pool_cleanup_file_t *cln; - + ngx_pool_cleanup_t *cln; + ngx_pool_cleanup_file_t *clnf; file->name.len = path->name.len + 1 + path->len + NGX_ATOMIC_T_LEN; @@ -66,6 +66,11 @@ ngx_create_temp_file(ngx_file_t *file, ngx_path_t *path, ngx_pool_t *pool, ngx_create_hashed_filename(file, path); + cln = ngx_pool_cleanup_add(pool, sizeof(ngx_pool_cleanup_file_t)); + if (cln == NULL) { + return NGX_ERROR; + } + #if 1 file->fd = ngx_open_tempfile(file->name.data, persistent); #else @@ -76,19 +81,13 @@ ngx_create_temp_file(ngx_file_t *file, ngx_path_t *path, ngx_pool_t *pool, "temp fd:%d", file->fd); if (file->fd != NGX_INVALID_FILE) { - cln = ngx_palloc(pool, sizeof(ngx_pool_cleanup_file_t)); - if (cln == NULL) { - return NGX_ERROR; - } - cln->fd = file->fd; - cln->name = file->name.data; - cln->log = pool->log; + cln->handler = ngx_pool_cleanup_file; + clnf = cln->data; - if (ngx_pool_cleanup_add(pool, ngx_pool_cleanup_file, cln) == NULL) - { - return NGX_ERROR; - } + clnf->fd = file->fd; + clnf->name = file->name.data; + clnf->log = pool->log; return NGX_OK; } diff --git a/src/core/ngx_palloc.c b/src/core/ngx_palloc.c index 9bb50f79c..d1e7bbdc5 100644 --- a/src/core/ngx_palloc.c +++ b/src/core/ngx_palloc.c @@ -207,7 +207,7 @@ ngx_pcalloc(ngx_pool_t *pool, size_t size) ngx_pool_cleanup_t * -ngx_pool_cleanup_add(ngx_pool_t *p, ngx_pool_cleanup_pt handler, void *data) +ngx_pool_cleanup_add(ngx_pool_t *p, size_t size) { ngx_pool_cleanup_t *c; @@ -216,12 +216,23 @@ ngx_pool_cleanup_add(ngx_pool_t *p, ngx_pool_cleanup_pt handler, void *data) return NULL; } - c->handler = handler; - c->data = data; + if (size) { + c->data = ngx_palloc(p, size); + if (c->data == NULL) { + return NULL; + } + + } else { + c->data = NULL; + } + + c->handler = NULL; c->next = p->cleanup; p->cleanup = c; + ngx_log_debug1(NGX_LOG_DEBUG_ALLOC, p->log, 0, "add cleanup: %p", c); + return c; } @@ -231,6 +242,9 @@ ngx_pool_cleanup_file(void *data) { ngx_pool_cleanup_file_t *c = data; + ngx_log_debug2(NGX_LOG_DEBUG_ALLOC, c->log, 0, "run cleanup: %p, fd:%d", + c, c->fd); + if (ngx_close_file(c->fd) == NGX_FILE_ERROR) { ngx_log_error(NGX_LOG_ALERT, c->log, ngx_errno, ngx_close_file_n " \"%s\" failed", c->name); diff --git a/src/core/ngx_palloc.h b/src/core/ngx_palloc.h index 62a571818..b8b169244 100644 --- a/src/core/ngx_palloc.h +++ b/src/core/ngx_palloc.h @@ -71,8 +71,7 @@ void *ngx_pcalloc(ngx_pool_t *pool, size_t size); ngx_int_t ngx_pfree(ngx_pool_t *pool, void *p); -ngx_pool_cleanup_t *ngx_pool_cleanup_add(ngx_pool_t *p, - ngx_pool_cleanup_pt handler, void *data); +ngx_pool_cleanup_t *ngx_pool_cleanup_add(ngx_pool_t *p, size_t size); void ngx_pool_cleanup_file(void *data); diff --git a/src/core/ngx_parse.c b/src/core/ngx_parse.c index dad9efcbd..f8e5f6c2e 100644 --- a/src/core/ngx_parse.c +++ b/src/core/ngx_parse.c @@ -8,11 +8,13 @@ #include -ngx_int_t ngx_parse_size(ngx_str_t *line) +ssize_t +ngx_parse_size(ngx_str_t *line) { u_char last; size_t len; - ngx_int_t scale, size; + ssize_t size; + ngx_int_t scale; len = line->len; last = line->data[len - 1]; @@ -34,7 +36,7 @@ ngx_int_t ngx_parse_size(ngx_str_t *line) scale = 1; } - size = ngx_atoi(line->data, len); + size = ngx_atosz(line->data, len); if (size == NGX_ERROR) { return NGX_ERROR; } @@ -45,7 +47,8 @@ ngx_int_t ngx_parse_size(ngx_str_t *line) } -ngx_int_t ngx_parse_time(ngx_str_t *line, ngx_int_t sec) +ngx_int_t +ngx_parse_time(ngx_str_t *line, ngx_int_t sec) { size_t len; u_char *start, last; diff --git a/src/core/ngx_parse.h b/src/core/ngx_parse.h index 44fff2e95..464cefcb8 100644 --- a/src/core/ngx_parse.h +++ b/src/core/ngx_parse.h @@ -15,7 +15,7 @@ #define NGX_PARSE_LARGE_TIME -2 -ngx_int_t ngx_parse_size(ngx_str_t *line); +ssize_t ngx_parse_size(ngx_str_t *line); ngx_int_t ngx_parse_time(ngx_str_t *line, ngx_int_t sec); diff --git a/src/core/ngx_radix_tree.c b/src/core/ngx_radix_tree.c index f82a5e5b7..957ec3099 100644 --- a/src/core/ngx_radix_tree.c +++ b/src/core/ngx_radix_tree.c @@ -205,6 +205,7 @@ ngx_radix32tree_delete(ngx_radix_tree_t *tree, uint32_t key, uint32_t mask) for ( ;; ) { if (node->parent->right == node) { node->parent->right = NULL; + } else { node->parent->left = NULL; } @@ -214,11 +215,15 @@ ngx_radix32tree_delete(ngx_radix_tree_t *tree, uint32_t key, uint32_t mask) node = node->parent; - if (node->right - || node->left - || node->value != NGX_RADIX_NO_VALUE - || node->parent == NULL) - { + if (node->right || node->left) { + break; + } + + if (node->value != NGX_RADIX_NO_VALUE) { + break; + } + + if (node->parent == NULL) { break; } } diff --git a/src/core/ngx_spinlock.c b/src/core/ngx_spinlock.c index 00e7fca7d..a3082a0a5 100644 --- a/src/core/ngx_spinlock.c +++ b/src/core/ngx_spinlock.c @@ -12,7 +12,8 @@ * TODO: the P4 optimized assembler version with the "pause" operation */ -void ngx_spinlock(ngx_atomic_t *lock, ngx_uint_t spin) +void +ngx_spinlock(ngx_atomic_t *lock, ngx_uint_t spin) { #if (NGX_HAVE_ATOMIC_OPS) diff --git a/src/core/ngx_times.c b/src/core/ngx_times.c index c806d55f8..88a9e98c9 100644 --- a/src/core/ngx_times.c +++ b/src/core/ngx_times.c @@ -8,61 +8,33 @@ #include -ngx_msec_t ngx_current_time; - -ngx_int_t ngx_gmtoff; - -static ngx_tm_t ngx_cached_gmtime; - - /* - * In the threaded mode only one thread updates the cached time and strings - * and these operations are protected by the mutex. The reading of the cached - * time and strings is not protected by the mutex. To avoid the race - * conditions for non-atomic values we use the NGX_TIME_SLOTS slots to store - * time value and strings. Thus thread may get the corrupted values only - * if it is preempted while copying and then it is not scheduled to run - * more than NGX_TIME_SLOTS seconds. + * The time may be updated by signal handler or by several threads. + * The time update operations are rare and require to hold the ngx_time_lock. + * The time read operations are frequent, so they are lock-free and get time + * values and strings from the current slot. Thus thread may get the corrupted + * values only if it is preempted while copying and then it is not scheduled + * to run more than NGX_TIME_SLOTS seconds. */ -#if (NGX_THREADS) +#define NGX_TIME_SLOTS 64 -#define NGX_TIME_SLOTS 60 -static ngx_uint_t slot = NGX_TIME_SLOTS; - -static ngx_mutex_t *ngx_time_mutex; - -#else +static ngx_uint_t slot = NGX_TIME_SLOTS; +static ngx_atomic_t ngx_time_lock; -#define NGX_TIME_SLOTS 1 -#define slot 0 +volatile ngx_msec_t ngx_current_msec; +volatile ngx_time_t *ngx_cached_time; +volatile ngx_str_t ngx_cached_err_log_time; +volatile ngx_str_t ngx_cached_http_time; +volatile ngx_str_t ngx_cached_http_log_time; -#endif - - -#if (NGX_THREADS && (NGX_TIME_T_SIZE > NGX_SIG_ATOMIC_T_SIZE)) - -volatile time_t *ngx_cached_time; -static time_t cached_time[NGX_TIME_SLOTS]; - -#else - -volatile time_t ngx_cached_time; - -#endif - - -ngx_thread_volatile ngx_str_t ngx_cached_err_log_time; -ngx_thread_volatile ngx_str_t ngx_cached_http_time; -ngx_thread_volatile ngx_str_t ngx_cached_http_log_time; - - -static u_char cached_err_log_time[NGX_TIME_SLOTS] - [sizeof("1970/09/28 12:00:00")]; -static u_char cached_http_time[NGX_TIME_SLOTS] - [sizeof("Mon, 28 Sep 1970 06:00:00 GMT")]; -static u_char cached_http_log_time[NGX_TIME_SLOTS] - [sizeof("28/Sep/1970:12:00:00 +0600")]; +static ngx_time_t cached_time[NGX_TIME_SLOTS]; +static u_char cached_err_log_time[NGX_TIME_SLOTS] + [sizeof("1970/09/28 12:00:00")]; +static u_char cached_http_time[NGX_TIME_SLOTS] + [sizeof("Mon, 28 Sep 1970 06:00:00 GMT")]; +static u_char cached_http_log_time[NGX_TIME_SLOTS] + [sizeof("28/Sep/1970:12:00:00 +0600")]; static char *week[] = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" }; @@ -72,63 +44,29 @@ static char *months[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", void ngx_time_init(void) { - struct timeval tv; - - ngx_memzero(&ngx_cached_gmtime, sizeof(ngx_tm_t)); -#ifdef ngx_tm_zone - ngx_cached_gmtime.ngx_tm_zone = "GMT"; -#endif - ngx_cached_err_log_time.len = sizeof("1970/09/28 12:00:00") - 1; ngx_cached_http_time.len = sizeof("Mon, 28 Sep 1970 06:00:00 GMT") - 1; ngx_cached_http_log_time.len = sizeof("28/Sep/1970:12:00:00 +0600") - 1; -#if (NGX_THREADS && (NGX_TIME_T_SIZE > NGX_SIG_ATOMIC_T_SIZE)) ngx_cached_time = &cached_time[0]; -#endif - - ngx_gettimeofday(&tv); - - ngx_current_time = (ngx_msec_t) tv.tv_sec * 1000 + tv.tv_usec / 1000; #if !(NGX_WIN32) tzset(); #endif - ngx_time_update(tv.tv_sec); -} - - -#if (NGX_THREADS) - -ngx_int_t -ngx_time_mutex_init(ngx_log_t *log) -{ - ngx_time_mutex = ngx_mutex_init(log, NGX_MUTEX_LIGHT); - - if (ngx_time_mutex == NULL) { - return NGX_ERROR; - } - - return NGX_OK; + ngx_time_update(0, 0); } -#endif - void -ngx_time_update(time_t s) +ngx_time_update(time_t sec, ngx_uint_t msec) { - u_char *p; - ngx_tm_t tm; - - if (ngx_time() == s) { - return; - } - -#if (NGX_THREADS) + u_char *p0, *p1, *p2; + ngx_tm_t tm, gmt; + ngx_time_t *tp; + struct timeval tv; - if (ngx_mutex_trylock(ngx_time_mutex) != NGX_OK) { + if (!ngx_trylock(&ngx_time_lock)) { return; } @@ -138,75 +76,80 @@ ngx_time_update(time_t s) slot++; } -#if (NGX_THREADS && (NGX_TIME_T_SIZE > NGX_SIG_ATOMIC_T_SIZE)) - ngx_cached_time = &cached_time[slot]; -#endif + if (sec == 0) { + ngx_gettimeofday(&tv); -#endif + sec = tv.tv_sec; + msec = tv.tv_usec / 1000; + } - ngx_time() = s; + ngx_current_msec = (ngx_msec_t) sec * 1000 + msec; - ngx_gmtime(s, &ngx_cached_gmtime); + tp = &cached_time[slot]; + tp->msec = msec; - p = cached_http_time[slot]; + if (tp->sec == sec) { + ngx_unlock(&ngx_time_lock); + return; + } + + tp->sec = sec; - (void) ngx_sprintf(p, "%s, %02d %s %4d %02d:%02d:%02d GMT", - week[ngx_cached_gmtime.ngx_tm_wday], - ngx_cached_gmtime.ngx_tm_mday, - months[ngx_cached_gmtime.ngx_tm_mon - 1], - ngx_cached_gmtime.ngx_tm_year, - ngx_cached_gmtime.ngx_tm_hour, - ngx_cached_gmtime.ngx_tm_min, - ngx_cached_gmtime.ngx_tm_sec); + ngx_gmtime(sec, &gmt); - ngx_cached_http_time.data = p; + p0 = cached_http_time[slot]; + + (void) ngx_sprintf(p0, "%s, %02d %s %4d %02d:%02d:%02d GMT", + week[gmt.ngx_tm_wday], gmt.ngx_tm_mday, + months[gmt.ngx_tm_mon - 1], gmt.ngx_tm_year, + gmt.ngx_tm_hour, gmt.ngx_tm_min, gmt.ngx_tm_sec); #if (NGX_HAVE_GETTIMEZONE) - ngx_gmtoff = ngx_gettimezone(); - ngx_gmtime(s + ngx_gmtoff * 60, &tm); + tp->gmtoff = ngx_gettimezone(); + ngx_gmtime(sec + tp->gmtoff * 60, &tm); #elif (NGX_HAVE_GMTOFF) - ngx_localtime(&tm); - ngx_gmtoff = (ngx_int_t) (tm.ngx_tm_gmtoff / 60); + ngx_localtime(sec, &tm); + tp->gmtoff = (ngx_int_t) (tm.ngx_tm_gmtoff / 60); #else - ngx_localtime(&tm); - ngx_gmtoff = ngx_timezone(tm.ngx_tm_isdst); + ngx_localtime(sec, &tm); + tp->gmtoff = ngx_timezone(tm.ngx_tm_isdst); #endif - p = cached_err_log_time[slot]; + p1 = cached_err_log_time[slot]; - (void) ngx_sprintf(p, "%4d/%02d/%02d %02d:%02d:%02d", + (void) ngx_sprintf(p1, "%4d/%02d/%02d %02d:%02d:%02d", tm.ngx_tm_year, tm.ngx_tm_mon, tm.ngx_tm_mday, tm.ngx_tm_hour, tm.ngx_tm_min, tm.ngx_tm_sec); - ngx_cached_err_log_time.data = p; - - p = cached_http_log_time[slot]; + p2 = cached_http_log_time[slot]; - (void) ngx_sprintf(p, "%02d/%s/%d:%02d:%02d:%02d %c%02d%02d", + (void) ngx_sprintf(p2, "%02d/%s/%d:%02d:%02d:%02d %c%02d%02d", tm.ngx_tm_mday, months[tm.ngx_tm_mon - 1], tm.ngx_tm_year, tm.ngx_tm_hour, tm.ngx_tm_min, tm.ngx_tm_sec, - ngx_gmtoff < 0 ? '-' : '+', - abs(ngx_gmtoff / 60), abs(ngx_gmtoff % 60)); + tp->gmtoff < 0 ? '-' : '+', + ngx_abs(tp->gmtoff / 60), ngx_abs(tp->gmtoff % 60)); - ngx_cached_http_log_time.data = p; + ngx_memory_barrier(); -#if (NGX_THREADS) - ngx_mutex_unlock(ngx_time_mutex); -#endif + ngx_cached_time = tp; + ngx_cached_http_time.data = p0; + ngx_cached_err_log_time.data = p1; + ngx_cached_http_log_time.data = p2; + ngx_unlock(&ngx_time_lock); } diff --git a/src/core/ngx_times.h b/src/core/ngx_times.h index bbcb41348..6e7ab638c 100644 --- a/src/core/ngx_times.h +++ b/src/core/ngx_times.h @@ -12,40 +12,34 @@ #include +typedef struct { + time_t sec; + ngx_uint_t msec; + ngx_int_t gmtoff; +} ngx_time_t; + + void ngx_time_init(void); -void ngx_time_update(time_t s); +void ngx_time_update(time_t sec, ngx_uint_t msec); u_char *ngx_http_time(u_char *buf, time_t t); u_char *ngx_http_cookie_time(u_char *buf, time_t t); void ngx_gmtime(time_t t, ngx_tm_t *tp); -#if (NGX_THREADS) -ngx_int_t ngx_time_mutex_init(ngx_log_t *log); -#endif - -#if (NGX_THREADS && (NGX_TIME_T_SIZE > NGX_SIG_ATOMIC_T_SIZE)) - -#define ngx_time() *ngx_cached_time -extern volatile time_t *ngx_cached_time; - -#else - -#define ngx_time() ngx_cached_time -extern volatile time_t ngx_cached_time; - -#endif +extern volatile ngx_time_t *ngx_cached_time; -extern ngx_thread_volatile ngx_str_t ngx_cached_err_log_time; -extern ngx_thread_volatile ngx_str_t ngx_cached_http_time; -extern ngx_thread_volatile ngx_str_t ngx_cached_http_log_time; +#define ngx_time() ngx_cached_time->sec +#define ngx_timeofday() (ngx_time_t *) ngx_cached_time -extern ngx_int_t ngx_gmtoff; +extern volatile ngx_str_t ngx_cached_err_log_time; +extern volatile ngx_str_t ngx_cached_http_time; +extern volatile ngx_str_t ngx_cached_http_log_time; /* * milliseconds elapsed since epoch and truncated to ngx_msec_t, * used in event timers */ -extern ngx_msec_t ngx_current_time; +extern volatile ngx_msec_t ngx_current_msec; #endif /* _NGX_TIMES_H_INCLUDED_ */ -- cgit v1.2.3