# HG changeset patch # User Igor Sysoev # Date 1139346000 -10800 # Node ID 73e8476f9142f5d6e509d6c2a53fb607290663ec # Parent 25c27e983933051646d67e369a766ff45480a708 nginx 0.3.27 *) Change: the "variables_hash_max_size" and "variables_hash_bucket_size" directives. *) Feature: the $body_bytes_sent variable can be used not only in the "log_format" directive. *) Feature: the $ssl_protocol and $ssl_cipher variables. *) Feature: the cache line size detection for widespread CPUs at start time. *) Feature: now the "accept_mutex" directive is supported using fcntl(2) on platforms different from i386, amd64, sparc64, and ppc. *) Feature: the "lock_file" directive and the --with-lock-path=PATH autoconfiguration directive. *) Bugfix: if the HTTPS protocol was used in the "proxy_pass" directive then the requests with the body was not transferred. diff --git a/CHANGES b/CHANGES --- a/CHANGES +++ b/CHANGES @@ -1,3 +1,26 @@ + +Changes with nginx 0.3.27 08 Feb 2006 + + *) Change: the "variables_hash_max_size" and + "variables_hash_bucket_size" directives. + + *) Feature: the $body_bytes_sent variable can be used not only in the + "log_format" directive. + + *) Feature: the $ssl_protocol and $ssl_cipher variables. + + *) Feature: the cache line size detection for widespread CPUs at start + time. + + *) Feature: now the "accept_mutex" directive is supported using + fcntl(2) on platforms different from i386, amd64, sparc64, and ppc. + + *) Feature: the "lock_file" directive and the --with-lock-path=PATH + autoconfiguration directive. + + *) Bugfix: if the HTTP protocol was used in the "proxy_pass" directive + then the requests with the body did not transferred. + Changes with nginx 0.3.26 03 Feb 2006 diff --git a/CHANGES.ru b/CHANGES.ru --- a/CHANGES.ru +++ b/CHANGES.ru @@ -1,3 +1,26 @@ + +Изменения в nginx 0.3.27 08.02.2006 + + *) Изменение: директивы variables_hash_max_size и + variables_hash_bucket_size. + + *) Добавление: переменная $body_bytes_sent доступна не только в + директиве log_format. + + *) Добавление: переменные $ssl_protocol и $ssl_cipher. + + *) Добавление: определение размера строки кэша распространённых + процессоров при старте. + + *) Добавление: директива accept_mutex теперь поддерживается посредством + fcntl(2) на платформах, отличных от i386, amd64, sparc64 и ppc. + + *) Добавление: директива lock_file и параметр автоконфигурации + --with-lock-path=PATH. + + *) Исправление: при использовании протокола HTTPS в директиве + proxy_pass не передавались запросы с телом. + Изменения в nginx 0.3.26 03.02.2006 diff --git a/auto/options b/auto/options --- a/auto/options +++ b/auto/options @@ -9,6 +9,7 @@ NGX_SBIN_PATH= NGX_CONF_PATH= NGX_ERROR_LOG_PATH= NGX_PID_PATH= +NGX_LOCK_PATH= NGX_USER= NGX_GROUP= @@ -112,6 +113,7 @@ do --conf-path=*) NGX_CONF_PATH="$value" ;; --error-log-path=*) NGX_ERROR_LOG_PATH="$value";; --pid-path=*) NGX_PID_PATH="$value" ;; + --lock-path=*) NGX_LOCK_PATH="$value" ;; --user=*) NGX_USER="$value" ;; --group=*) NGX_GROUP="$value" ;; @@ -212,6 +214,7 @@ cat << END --conf-path=PATH set path to the nginx.conf file --error-log-path=PATH set path to the error log --pid-path=PATH set path to nginx.pid file + --lock-path=PATH set path to nginx.lock file --user=USER set non-privilege user for the worker processes @@ -354,6 +357,20 @@ case ".$NGX_PID_PATH" in esac +case ".$NGX_LOCK_PATH" in + ./*) + ;; + + .) + NGX_LOCK_PATH=$NGX_PREFIX/logs/nginx.lock + ;; + + *) + NGX_LOCK_PATH=$NGX_PREFIX/$NGX_LOCK_PATH + ;; +esac + + case ".$NGX_ERROR_LOG_PATH" in ./*) ;; diff --git a/auto/sources b/auto/sources --- a/auto/sources +++ b/auto/sources @@ -23,6 +23,7 @@ CORE_DEPS="src/core/nginx.h \ src/core/ngx_rbtree.h \ src/core/ngx_radix_tree.h \ src/core/ngx_times.h \ + src/core/ngx_shmtx.h \ src/core/ngx_connection.h \ src/core/ngx_cycle.h \ src/core/ngx_conf_file.h \ @@ -44,9 +45,11 @@ CORE_SRCS="src/core/nginx.c \ src/core/ngx_rbtree.c \ src/core/ngx_radix_tree.c \ src/core/ngx_times.c \ + src/core/ngx_shmtx.c \ src/core/ngx_connection.c \ src/core/ngx_cycle.c \ src/core/ngx_spinlock.c \ + src/core/ngx_cpuinfo.c \ src/core/ngx_conf_file.c \ src/core/ngx_garbage_collector.c" diff --git a/conf/nginx.conf b/conf/nginx.conf --- a/conf/nginx.conf +++ b/conf/nginx.conf @@ -56,7 +56,7 @@ http { #location ~ \.php$ { # fastcgi_pass 127.0.0.1:9000; # fastcgi_index index.php; - # fastcgi_param PATH_TRANSLATED /scripts$fastcgi_script_name; + # fastcgi_param SCRIPT_FILENAME /scripts$fastcgi_script_name; # include conf/fastcgi_params; #} diff --git a/configure b/configure --- a/configure +++ b/configure @@ -65,6 +65,7 @@ have=NGX_PREFIX value="\"$NGX_PREFIX/\"" have=NGX_SBIN_PATH value="\"$NGX_SBIN_PATH\"" . auto/define have=NGX_CONF_PATH value="\"$NGX_CONF_PATH\"" . auto/define have=NGX_PID_PATH value="\"$NGX_PID_PATH\"" . auto/define +have=NGX_LOCK_PATH value="\"$NGX_LOCK_PATH\"" . auto/define if test -n "$NGX_ERROR_LOG_PATH"; then have=NGX_ERROR_LOG_PATH value="\"$NGX_ERROR_LOG_PATH\"" . auto/define fi diff --git a/src/core/nginx.c b/src/core/nginx.c --- a/src/core/nginx.c +++ b/src/core/nginx.c @@ -58,6 +58,13 @@ static ngx_command_t ngx_core_commands[ offsetof(ngx_core_conf_t, pid), NULL }, + { ngx_string("lock_file"), + NGX_MAIN_CONF|NGX_DIRECT_CONF|NGX_CONF_TAKE1, + ngx_conf_set_str_slot, + 0, + offsetof(ngx_core_conf_t, lock_file), + NULL }, + { ngx_string("worker_processes"), NGX_MAIN_CONF|NGX_DIRECT_CONF|NGX_CONF_TAKE1, ngx_conf_set_num_slot, @@ -214,11 +221,11 @@ main(int argc, char *const *argv) return 1; } - if (ngx_save_argv(&init_cycle, argc, argv) == NGX_ERROR) { + if (ngx_save_argv(&init_cycle, argc, argv) != NGX_OK) { return 1; } - if (ngx_getopt(&init_cycle, argc, ngx_argv) == NGX_ERROR) { + if (ngx_getopt(&init_cycle, argc, ngx_argv) != NGX_OK) { return 1; } @@ -226,11 +233,11 @@ main(int argc, char *const *argv) log->log_level = NGX_LOG_INFO; } - if (ngx_os_init(log) == NGX_ERROR) { + if (ngx_os_init(log) != NGX_OK) { return 1; } - if (ngx_add_inherited_sockets(&init_cycle) == NGX_ERROR) { + if (ngx_add_inherited_sockets(&init_cycle) != NGX_OK) { return 1; } @@ -274,7 +281,7 @@ main(int argc, char *const *argv) TODO: if (ccf->run_as_service) { - if (ngx_service(cycle->log) == NGX_ERROR) { + if (ngx_service(cycle->log) != NGX_OK) { return 1; } @@ -284,19 +291,19 @@ main(int argc, char *const *argv) #else - if (ngx_init_signals(cycle->log) == NGX_ERROR) { + if (ngx_init_signals(cycle->log) != NGX_OK) { return 1; } if (!ngx_inherited && ccf->daemon) { - if (ngx_daemon(cycle->log) == NGX_ERROR) { + if (ngx_daemon(cycle->log) != NGX_OK) { return 1; } ngx_daemonized = 1; } - if (ngx_create_pidfile(cycle, NULL) == NGX_ERROR) { + if (ngx_create_pidfile(&ccf->pid, cycle->log) != NGX_OK) { return 1; } @@ -666,6 +673,15 @@ ngx_core_module_init_conf(ngx_cycle_t *c ngx_memcpy(ngx_cpymem(ccf->oldpid.data, ccf->pid.data, ccf->pid.len), NGX_OLDPID_EXT, sizeof(NGX_OLDPID_EXT)); + if (ccf->lock_file.len == 0) { + ccf->lock_file.len = sizeof(NGX_LOCK_PATH) - 1; + ccf->lock_file.data = (u_char *) NGX_LOCK_PATH; + } + + if (ngx_conf_full_name(cycle, &ccf->lock_file) == NGX_ERROR) { + return NGX_CONF_ERROR; + } + #endif return NGX_CONF_OK; diff --git a/src/core/nginx.h b/src/core/nginx.h --- a/src/core/nginx.h +++ b/src/core/nginx.h @@ -8,7 +8,7 @@ #define _NGINX_H_INCLUDED_ -#define NGINX_VER "nginx/0.3.26" +#define NGINX_VER "nginx/0.3.27" #define NGINX_VAR "NGINX" #define NGX_OLDPID_EXT ".oldbin" diff --git a/src/core/ngx_connection.c b/src/core/ngx_connection.c --- a/src/core/ngx_connection.c +++ b/src/core/ngx_connection.c @@ -495,7 +495,7 @@ ngx_close_listening_sockets(ngx_cycle_t } ngx_accept_mutex_held = 0; - ngx_accept_mutex = NULL; + ngx_use_accept_mutex = 0; ls = cycle->listening.elts; for (i = 0; i < cycle->listening.nelts; i++) { @@ -726,7 +726,6 @@ ngx_connection_error(ngx_connection_t *c || err == NGX_ECONNREFUSED || err == NGX_EHOSTUNREACH) { - switch (c->log_error) { case NGX_ERROR_IGNORE_ECONNRESET: diff --git a/src/core/ngx_core.h b/src/core/ngx_core.h --- a/src/core/ngx_core.h +++ b/src/core/ngx_core.h @@ -62,6 +62,7 @@ typedef void (*ngx_connection_handler_pt #endif #include #include +#include #include #if (NGX_HAVE_UNIX_DOMAIN) #include @@ -83,5 +84,7 @@ typedef void (*ngx_connection_handler_pt #define ngx_abs(value) (((value) >= 0) ? (value) : - (value)) +void ngx_cpuinfo(void); + #endif /* _NGX_CORE_H_INCLUDED_ */ diff --git a/src/core/ngx_cpuinfo.c b/src/core/ngx_cpuinfo.c new file mode 100644 --- /dev/null +++ b/src/core/ngx_cpuinfo.c @@ -0,0 +1,93 @@ + +/* + * Copyright (C) Igor Sysoev + */ + + +#include +#include + + +#if (( __i386__ || __amd64__ ) && ( __GNUC__ || __INTEL_COMPILER )) + + +static ngx_inline void ngx_cpuid(uint32_t i, uint32_t *buf); + + +static ngx_inline void +ngx_cpuid(uint32_t i, uint32_t *buf) +{ + uint32_t eax, ebx, ecx, edx; + + __asm__ ( + + "cpuid" + + : "=a" (eax), "=b" (ebx), "=c" (ecx), "=d" (edx) : "a" (i) ); + + buf[0] = eax; + buf[1] = ebx; + buf[2] = edx; + buf[3] = ecx; +} + + +/* auto detect the L2 cache line size of modern and widespread CPUs */ + +void +ngx_cpuinfo(void) +{ + u_char *vendor; + uint32_t vbuf[5], cpu[4]; + + vbuf[0] = 0; + vbuf[1] = 0; + vbuf[2] = 0; + vbuf[3] = 0; + vbuf[4] = 0; + + ngx_cpuid(0, vbuf); + + vendor = (u_char *) &vbuf[1]; + + if (vbuf[0] == 0) { + return; + } + + ngx_cpuid(1, cpu); + + if (ngx_strcmp(vendor, "GenuineIntel") == 0) { + + switch (cpu[0] & 0xf00) { + + /* Pentium */ + case 5: + /* Pentium Pro, II, III */ + case 6: + ngx_cacheline_size = 32; + break; + + /* + * Pentium 4, although its cache line size is 64 bytes, + * it prefetches up to two cache lines during memory read + */ + case 15: + ngx_cacheline_size = 128; + break; + } + + } else if (ngx_strcmp(vendor, "AuthenticAMD") == 0) { + ngx_cacheline_size = 64; + } +} + +#else + + +void +ngx_cpuinfo(void) +{ +} + + +#endif diff --git a/src/core/ngx_cycle.c b/src/core/ngx_cycle.c --- a/src/core/ngx_cycle.c +++ b/src/core/ngx_cycle.c @@ -9,6 +9,7 @@ #include +static ngx_int_t ngx_test_lockfile(u_char *file, ngx_log_t *log); static void ngx_destroy_cycle_pools(ngx_conf_t *conf); static ngx_int_t ngx_cmp_sockaddr(struct sockaddr *sa1, struct sockaddr *sa2); static void ngx_clean_old_cycles(ngx_event_t *ev); @@ -42,7 +43,7 @@ ngx_cycle_t * ngx_init_cycle(ngx_cycle_t *old_cycle) { void *rv; - ngx_uint_t i, n, failed; + ngx_uint_t i, n; ngx_log_t *log; ngx_conf_t conf; ngx_pool_t *pool; @@ -52,7 +53,9 @@ ngx_init_cycle(ngx_cycle_t *old_cycle) ngx_listening_t *ls, *nls; ngx_core_conf_t *ccf; ngx_core_module_t *module; - +#if !(WIN32) + ngx_core_conf_t *old_ccf; +#endif log = old_cycle->log; @@ -236,82 +239,100 @@ ngx_init_cycle(ngx_cycle_t *old_cycle) } - failed = 0; - + ccf = (ngx_core_conf_t *) ngx_get_conf(cycle->conf_ctx, ngx_core_module); #if !(NGX_WIN32) - if (ngx_create_pidfile(cycle, old_cycle) == NGX_ERROR) { - failed = 1; + + if (ngx_test_config) { + + if (ngx_create_pidfile(&ccf->pid, log) != NGX_OK) { + goto failed; + } + + } else if (!ngx_is_init_cycle(old_cycle)) { + + /* + * we do not create the pid file in the first ngx_init_cycle() call + * because we need to write the demonized process pid + */ + + old_ccf = (ngx_core_conf_t *) ngx_get_conf(old_cycle->conf_ctx, + ngx_core_module); + if (ccf->pid.len != old_ccf->pid.len + || ngx_strcmp(ccf->pid.data, old_ccf->pid.data) != 0) + { + /* new pid file name */ + + if (ngx_create_pidfile(&ccf->pid, log) != NGX_OK) { + goto failed; + } + + ngx_delete_pidfile(old_cycle); + } } + #endif - if (!failed) { - ccf = (ngx_core_conf_t *) ngx_get_conf(cycle->conf_ctx, - ngx_core_module); + if (ngx_test_lockfile(ccf->lock_file.data, log) != NGX_OK) { + goto failed; + } - if (ngx_create_pathes(cycle, ccf->user) == NGX_ERROR) { - failed = 1; - } + + if (ngx_create_pathes(cycle, ccf->user) != NGX_OK) { + goto failed; } - if (!failed) { - - /* open the new files */ - - part = &cycle->open_files.part; - file = part->elts; - - for (i = 0; /* void */ ; i++) { + /* open the new files */ - if (i >= part->nelts) { - if (part->next == NULL) { - break; - } - part = part->next; - file = part->elts; - i = 0; - } + part = &cycle->open_files.part; + file = part->elts; - if (file[i].name.data == NULL) { - continue; - } - - file[i].fd = ngx_open_file(file[i].name.data, - NGX_FILE_RDWR, - NGX_FILE_CREATE_OR_OPEN|NGX_FILE_APPEND); + for (i = 0; /* void */ ; i++) { - ngx_log_debug3(NGX_LOG_DEBUG_CORE, log, 0, - "log: %p %d \"%s\"", - &file[i], file[i].fd, file[i].name.data); - - if (file[i].fd == NGX_INVALID_FILE) { - ngx_log_error(NGX_LOG_EMERG, log, ngx_errno, - ngx_open_file_n " \"%s\" failed", - file[i].name.data); - failed = 1; + if (i >= part->nelts) { + if (part->next == NULL) { break; } + part = part->next; + file = part->elts; + i = 0; + } + + if (file[i].name.data == NULL) { + continue; + } + + file[i].fd = ngx_open_file(file[i].name.data, NGX_FILE_RDWR, + NGX_FILE_CREATE_OR_OPEN|NGX_FILE_APPEND); + + ngx_log_debug3(NGX_LOG_DEBUG_CORE, log, 0, + "log: %p %d \"%s\"", + &file[i], file[i].fd, file[i].name.data); + + if (file[i].fd == NGX_INVALID_FILE) { + ngx_log_error(NGX_LOG_EMERG, log, ngx_errno, + ngx_open_file_n " \"%s\" failed", + file[i].name.data); + goto failed; + } #if (NGX_WIN32) - if (ngx_file_append_mode(file[i].fd) == NGX_ERROR) { - ngx_log_error(NGX_LOG_EMERG, log, ngx_errno, - ngx_file_append_mode_n " \"%s\" failed", - file[i].name.data); - failed = 1; - break; - } + if (ngx_file_append_mode(file[i].fd) != NGX_OK) { + ngx_log_error(NGX_LOG_EMERG, log, ngx_errno, + ngx_file_append_mode_n " \"%s\" failed", + file[i].name.data); + goto failed; + } #else - if (fcntl(file[i].fd, F_SETFD, FD_CLOEXEC) == -1) { - ngx_log_error(NGX_LOG_EMERG, log, ngx_errno, - "fcntl(FD_CLOEXEC) \"%s\" failed", - file[i].name.data); - failed = 1; - break; - } + if (fcntl(file[i].fd, F_SETFD, FD_CLOEXEC) == -1) { + ngx_log_error(NGX_LOG_EMERG, log, ngx_errno, + "fcntl(FD_CLOEXEC) \"%s\" failed", + file[i].name.data); + goto failed; + } #endif - } } cycle->log = cycle->new_log; @@ -321,159 +342,100 @@ ngx_init_cycle(ngx_cycle_t *old_cycle) cycle->log->log_level = NGX_LOG_ERR; } - if (!failed) { - /* handle the listening sockets */ + /* handle the listening sockets */ - if (old_cycle->listening.nelts) { - ls = old_cycle->listening.elts; - for (i = 0; i < old_cycle->listening.nelts; i++) { - ls[i].remain = 0; - } + if (old_cycle->listening.nelts) { + ls = old_cycle->listening.elts; + for (i = 0; i < old_cycle->listening.nelts; i++) { + ls[i].remain = 0; + } - nls = cycle->listening.elts; - for (n = 0; n < cycle->listening.nelts; n++) { + nls = cycle->listening.elts; + for (n = 0; n < cycle->listening.nelts; n++) { - for (i = 0; i < old_cycle->listening.nelts; i++) { - if (ls[i].ignore) { - continue; - } + for (i = 0; i < old_cycle->listening.nelts; i++) { + if (ls[i].ignore) { + continue; + } - if (ngx_cmp_sockaddr(nls[n].sockaddr, ls[i].sockaddr) - == NGX_OK) - { - nls[n].fd = ls[i].fd; - nls[n].previous = &ls[i]; - ls[i].remain = 1; + if (ngx_cmp_sockaddr(nls[n].sockaddr, ls[i].sockaddr) == NGX_OK) + { + nls[n].fd = ls[i].fd; + nls[n].previous = &ls[i]; + ls[i].remain = 1; - if (ls[n].backlog != nls[i].backlog) { - nls[n].listen = 1; - } + if (ls[n].backlog != nls[i].backlog) { + nls[n].listen = 1; + } #if (NGX_HAVE_DEFERRED_ACCEPT && defined SO_ACCEPTFILTER) - /* - * FreeBSD, except the most recent versions, - * could not remove accept filter - */ - nls[n].deferred_accept = ls[i].deferred_accept; + /* + * FreeBSD, except the most recent versions, + * could not remove accept filter + */ + nls[n].deferred_accept = ls[i].deferred_accept; - if (ls[i].accept_filter && nls[n].accept_filter) { - if (ngx_strcmp(ls[i].accept_filter, - nls[n].accept_filter) != 0) - { - nls[n].delete_deferred = 1; - nls[n].add_deferred = 1; - } - - } else if (ls[i].accept_filter) { + if (ls[i].accept_filter && nls[n].accept_filter) { + if (ngx_strcmp(ls[i].accept_filter, + nls[n].accept_filter) + != 0) + { nls[n].delete_deferred = 1; - - } else if (nls[n].accept_filter) { nls[n].add_deferred = 1; } + + } else if (ls[i].accept_filter) { + nls[n].delete_deferred = 1; + + } else if (nls[n].accept_filter) { + nls[n].add_deferred = 1; + } #endif #if (NGX_HAVE_DEFERRED_ACCEPT && defined TCP_DEFER_ACCEPT) - if (ls[n].deferred_accept && !nls[n].deferred_accept) { - nls[n].delete_deferred = 1; + if (ls[n].deferred_accept && !nls[n].deferred_accept) { + nls[n].delete_deferred = 1; - } else if (ls[i].deferred_accept - != nls[n].deferred_accept) - { - nls[n].add_deferred = 1; - } + } else if (ls[i].deferred_accept != nls[n].deferred_accept) + { + nls[n].add_deferred = 1; + } #endif - break; - } - } - - if (nls[n].fd == -1) { - nls[n].open = 1; + break; } } - } else { - ls = cycle->listening.elts; - for (i = 0; i < cycle->listening.nelts; i++) { - ls[i].open = 1; -#if (NGX_HAVE_DEFERRED_ACCEPT && defined SO_ACCEPTFILTER) - if (ls[i].accept_filter) { - ls[i].add_deferred = 1; - } -#endif -#if (NGX_HAVE_DEFERRED_ACCEPT && defined TCP_DEFER_ACCEPT) - if (ls[i].deferred_accept) { - ls[i].add_deferred = 1; - } -#endif + if (nls[n].fd == -1) { + nls[n].open = 1; } } - if (!failed) { - if (ngx_open_listening_sockets(cycle) == NGX_ERROR) { - failed = 1; + } else { + ls = cycle->listening.elts; + for (i = 0; i < cycle->listening.nelts; i++) { + ls[i].open = 1; +#if (NGX_HAVE_DEFERRED_ACCEPT && defined SO_ACCEPTFILTER) + if (ls[i].accept_filter) { + ls[i].add_deferred = 1; } - - if (!ngx_test_config && !failed) { - ngx_configure_listening_socket(cycle); +#endif +#if (NGX_HAVE_DEFERRED_ACCEPT && defined TCP_DEFER_ACCEPT) + if (ls[i].deferred_accept) { + ls[i].add_deferred = 1; } +#endif } } - - if (failed) { - - /* rollback the new cycle configuration */ - - part = &cycle->open_files.part; - file = part->elts; - - for (i = 0; /* void */ ; i++) { - - if (i >= part->nelts) { - if (part->next == NULL) { - break; - } - part = part->next; - file = part->elts; - i = 0; - } - - if (file[i].fd == NGX_INVALID_FILE - || file[i].fd == ngx_stderr_fileno) - { - continue; - } + if (ngx_open_listening_sockets(cycle) != NGX_OK) { + goto failed; + } - if (ngx_close_file(file[i].fd) == NGX_FILE_ERROR) { - ngx_log_error(NGX_LOG_EMERG, log, ngx_errno, - ngx_close_file_n " \"%s\" failed", - file[i].name.data); - } - } - - if (ngx_test_config) { - ngx_destroy_cycle_pools(&conf); - return NULL; - } - - ls = cycle->listening.elts; - for (i = 0; i < cycle->listening.nelts; i++) { - if (ls[i].fd == -1 || !ls[i].open) { - continue; - } - - if (ngx_close_socket(ls[i].fd) == -1) { - ngx_log_error(NGX_LOG_EMERG, log, ngx_socket_errno, - ngx_close_socket_n " %V failed", - &ls[i].addr_text); - } - } - - ngx_destroy_cycle_pools(&conf); - return NULL; + if (!ngx_test_config) { + ngx_configure_listening_socket(cycle); } @@ -488,7 +450,7 @@ ngx_init_cycle(ngx_cycle_t *old_cycle) cycle->log->file, cycle->log->file->fd, cycle->log->file->name.data); - if (dup2(cycle->log->file->fd, STDERR_FILENO) == NGX_ERROR) { + if (dup2(cycle->log->file->fd, STDERR_FILENO) == -1) { ngx_log_error(NGX_LOG_EMERG, log, ngx_errno, "dup2(STDERR) failed"); /* fatal */ @@ -502,7 +464,7 @@ ngx_init_cycle(ngx_cycle_t *old_cycle) for (i = 0; ngx_modules[i]; i++) { if (ngx_modules[i]->init_module) { - if (ngx_modules[i]->init_module(cycle) == NGX_ERROR) { + if (ngx_modules[i]->init_module(cycle) != NGX_OK) { /* fatal */ exit(1); } @@ -564,6 +526,9 @@ ngx_init_cycle(ngx_cycle_t *old_cycle) } ngx_destroy_pool(old_cycle->pool); + + cycle->old_cycle = NULL; + return cycle; } @@ -607,6 +572,58 @@ ngx_init_cycle(ngx_cycle_t *old_cycle) } return cycle; + + +failed: + + /* rollback the new cycle configuration */ + + part = &cycle->open_files.part; + file = part->elts; + + for (i = 0; /* void */ ; i++) { + + if (i >= part->nelts) { + if (part->next == NULL) { + break; + } + part = part->next; + file = part->elts; + i = 0; + } + + if (file[i].fd == NGX_INVALID_FILE || file[i].fd == ngx_stderr_fileno) { + continue; + } + + if (ngx_close_file(file[i].fd) == NGX_FILE_ERROR) { + ngx_log_error(NGX_LOG_EMERG, log, ngx_errno, + ngx_close_file_n " \"%s\" failed", + file[i].name.data); + } + } + + if (ngx_test_config) { + ngx_destroy_cycle_pools(&conf); + return NULL; + } + + ls = cycle->listening.elts; + for (i = 0; i < cycle->listening.nelts; i++) { + if (ls[i].fd == -1 || !ls[i].open) { + continue; + } + + if (ngx_close_socket(ls[i].fd) == -1) { + ngx_log_error(NGX_LOG_EMERG, log, ngx_socket_errno, + ngx_close_socket_n " %V failed", + &ls[i].addr_text); + } + } + + ngx_destroy_cycle_pools(&conf); + + return NULL; } @@ -651,52 +668,25 @@ ngx_cmp_sockaddr(struct sockaddr *sa1, s #if !(NGX_WIN32) ngx_int_t -ngx_create_pidfile(ngx_cycle_t *cycle, ngx_cycle_t *old_cycle) +ngx_create_pidfile(ngx_str_t *name, ngx_log_t *log) { + size_t len; ngx_uint_t trunc; - size_t len; - u_char pid[NGX_INT64_LEN]; ngx_file_t file; - ngx_core_conf_t *ccf, *old_ccf; - - if (!ngx_test_config && ngx_is_init_cycle(old_cycle)) { - - /* - * do not create the pid file in the first ngx_init_cycle() call - * because we need to write the demonized process pid - */ - - return NGX_OK; - } - - ccf = (ngx_core_conf_t *) ngx_get_conf(cycle->conf_ctx, ngx_core_module); - - if (!ngx_test_config && old_cycle) { - old_ccf = (ngx_core_conf_t *) ngx_get_conf(old_cycle->conf_ctx, - ngx_core_module); - - if (ccf->pid.len == old_ccf->pid.len - && ngx_strcmp(ccf->pid.data, old_ccf->pid.data) == 0) - { - - /* pid file name is the same */ - - return NGX_OK; - } - } + u_char pid[NGX_INT64_LEN]; ngx_memzero(&file, sizeof(ngx_file_t)); - file.name = ccf->pid; - file.log = cycle->log; + file.name = *name; + file.log = log; - trunc = ngx_test_config ? 0: NGX_FILE_TRUNCATE; + trunc = ngx_test_config ? 0 : NGX_FILE_TRUNCATE; file.fd = ngx_open_file(file.name.data, NGX_FILE_RDWR, NGX_FILE_CREATE_OR_OPEN|trunc); if (file.fd == NGX_INVALID_FILE) { - ngx_log_error(NGX_LOG_EMERG, cycle->log, ngx_errno, + ngx_log_error(NGX_LOG_EMERG, log, ngx_errno, ngx_open_file_n " \"%s\" failed", file.name.data); return NGX_ERROR; } @@ -710,12 +700,10 @@ ngx_create_pidfile(ngx_cycle_t *cycle, n } if (ngx_close_file(file.fd) == NGX_FILE_ERROR) { - ngx_log_error(NGX_LOG_ALERT, cycle->log, ngx_errno, + ngx_log_error(NGX_LOG_ALERT, log, ngx_errno, ngx_close_file_n " \"%s\" failed", file.name.data); } - ngx_delete_pidfile(old_cycle); - return NGX_OK; } @@ -726,10 +714,6 @@ ngx_delete_pidfile(ngx_cycle_t *cycle) u_char *name; ngx_core_conf_t *ccf; - if (cycle == NULL || cycle->conf_ctx == NULL) { - return; - } - ccf = (ngx_core_conf_t *) ngx_get_conf(cycle->conf_ctx, ngx_core_module); name = ngx_new_binary ? ccf->oldpid.data : ccf->pid.data; @@ -743,6 +727,36 @@ ngx_delete_pidfile(ngx_cycle_t *cycle) #endif +static ngx_int_t +ngx_test_lockfile(u_char *file, ngx_log_t *log) +{ +#if !(NGX_HAVE_ATOMIC_OPS) + ngx_fd_t fd; + + fd = ngx_open_file(file, NGX_FILE_RDWR, NGX_FILE_CREATE_OR_OPEN); + + if (fd == NGX_INVALID_FILE) { + ngx_log_error(NGX_LOG_EMERG, log, ngx_errno, + ngx_open_file_n " \"%s\" failed", file); + return NGX_ERROR; + } + + if (ngx_close_file(fd) == NGX_FILE_ERROR) { + ngx_log_error(NGX_LOG_ALERT, log, ngx_errno, + ngx_close_file_n " \"%s\" failed", file); + } + + if (ngx_delete_file(file) == NGX_FILE_ERROR) { + ngx_log_error(NGX_LOG_ALERT, log, ngx_errno, + ngx_delete_file_n " \"%s\" failed", file); + } + +#endif + + return NGX_OK; +} + + void ngx_reopen_files(ngx_cycle_t *cycle, ngx_uid_t user) { diff --git a/src/core/ngx_cycle.h b/src/core/ngx_cycle.h --- a/src/core/ngx_cycle.h +++ b/src/core/ngx_cycle.h @@ -77,6 +77,7 @@ typedef struct { ngx_gid_t group; ngx_str_t working_directory; + ngx_str_t lock_file; ngx_str_t pid; ngx_str_t oldpid; @@ -94,11 +95,11 @@ typedef struct { } ngx_core_tls_t; -#define ngx_is_init_cycle(old) (old && old->conf_ctx == NULL) +#define ngx_is_init_cycle(cycle) (cycle->conf_ctx == NULL) ngx_cycle_t *ngx_init_cycle(ngx_cycle_t *old_cycle); -ngx_int_t ngx_create_pidfile(ngx_cycle_t *cycle, ngx_cycle_t *old_cycle); +ngx_int_t ngx_create_pidfile(ngx_str_t *name, ngx_log_t *log); void ngx_delete_pidfile(ngx_cycle_t *cycle); void ngx_reopen_files(ngx_cycle_t *cycle, ngx_uid_t user); ngx_pid_t ngx_exec_new_binary(ngx_cycle_t *cycle, char *const *argv); diff --git a/src/core/ngx_shmtx.c b/src/core/ngx_shmtx.c new file mode 100644 --- /dev/null +++ b/src/core/ngx_shmtx.c @@ -0,0 +1,70 @@ + +/* + * Copyright (C) Igor Sysoev + */ + + +#include +#include + + +#if (NGX_HAVE_ATOMIC_OPS) + + +ngx_int_t +ngx_shmtx_create(ngx_shmtx_t *mtx, void *addr, u_char *name, ngx_log_t *log) +{ + mtx->lock = addr; + + return NGX_OK; +} + +#else + + +ngx_int_t +ngx_shmtx_create(ngx_shmtx_t *mtx, void *addr, u_char *name, ngx_log_t *log) +{ + if (mtx->name) { + + if (ngx_strcmp(name, mtx->name) == 0) { + mtx->name = name; + mtx->log = log; + + return NGX_OK; + } + + ngx_shmtx_destory(mtx); + } + + mtx->fd = ngx_open_file(name, NGX_FILE_RDWR, NGX_FILE_CREATE_OR_OPEN); + + if (mtx->fd == NGX_INVALID_FILE) { + ngx_log_error(NGX_LOG_EMERG, log, ngx_errno, + ngx_open_file_n " \"%s\" failed", name); + return NGX_ERROR; + } + + if (ngx_delete_file(name) == NGX_FILE_ERROR) { + ngx_log_error(NGX_LOG_ALERT, log, ngx_errno, + ngx_delete_file_n " \"%s\" failed", name); + } + + mtx->name = name; + mtx->log = log; + + return NGX_OK; +} + + +void +ngx_shmtx_destory(ngx_shmtx_t *mtx) +{ + if (ngx_close_file(mtx->fd) == NGX_FILE_ERROR) { + ngx_log_error(NGX_LOG_ALERT, mtx->log, ngx_errno, + ngx_close_file_n " \"%s\" failed", mtx->name); + } +} + + +#endif diff --git a/src/core/ngx_shmtx.h b/src/core/ngx_shmtx.h new file mode 100644 --- /dev/null +++ b/src/core/ngx_shmtx.h @@ -0,0 +1,111 @@ + +/* + * Copyright (C) Igor Sysoev + */ + + +#ifndef _NGX_SHMTX_H_INCLUDED_ +#define _NGX_SHMTX_H_INCLUDED_ + + +#include +#include + + +typedef struct { +#if (NGX_HAVE_ATOMIC_OPS) + ngx_atomic_t *lock; +#else + ngx_fd_t fd; + u_char *name; + ngx_log_t *log; +#endif +} ngx_shmtx_t; + + +ngx_int_t ngx_shmtx_create(ngx_shmtx_t *mtx, void *addr, u_char *name, + ngx_log_t *log); + + +#if (NGX_HAVE_ATOMIC_OPS) + +static ngx_inline ngx_uint_t +ngx_shmtx_trylock(ngx_shmtx_t *mtx) +{ + if (*mtx->lock == 0 && ngx_atomic_cmp_set(mtx->lock, 0, ngx_pid)) { + return 1; + } + + return 0; +} + +#define ngx_shmtx_lock(mtx) ngx_spinlock((mtx)->lock, ngx_pid, 1024) + +#define ngx_shmtx_unlock(mtx) (void) ngx_atomic_cmp_set((mtx)->lock, ngx_pid, 0) + +#define ngx_shmtx_destory(mtx) + + +#else + +static ngx_inline ngx_uint_t +ngx_shmtx_trylock(ngx_shmtx_t *mtx) +{ + ngx_err_t err; + + err = ngx_trylock_fd(mtx->fd); + + if (err == 0) { + return 1; + } + + if (err == NGX_EAGAIN) { + return 0; + } + + ngx_log_error(NGX_LOG_ALERT, mtx->log, err, ngx_trylock_fd_n " failed"); + + ngx_abort(); +} + + +static ngx_inline void +ngx_shmtx_lock(ngx_shmtx_t *mtx) +{ + ngx_err_t err; + + err = ngx_lock_fd(mtx->fd); + + if (err == 0) { + return; + } + + ngx_log_error(NGX_LOG_ALERT, mtx->log, err, ngx_lock_fd_n " failed"); + + ngx_abort(); +} + + +static ngx_inline void +ngx_shmtx_unlock(ngx_shmtx_t *mtx) +{ + ngx_err_t err; + + err = ngx_unlock_fd(mtx->fd); + + if (err == 0) { + return; + } + + ngx_log_error(NGX_LOG_ALERT, mtx->log, err, ngx_unlock_fd_n " failed"); + + ngx_abort(); +} + + +void ngx_shmtx_destory(ngx_shmtx_t *mtx); + +#endif + + +#endif /* _NGX_SHMTX_H_INCLUDED_ */ diff --git a/src/core/ngx_spinlock.c b/src/core/ngx_spinlock.c --- a/src/core/ngx_spinlock.c +++ b/src/core/ngx_spinlock.c @@ -8,36 +8,35 @@ #include -/* - * TODO: the P4 optimized assembler version with the "pause" operation - */ - void -ngx_spinlock(ngx_atomic_t *lock, ngx_uint_t spin) +ngx_spinlock(ngx_atomic_t *lock, ngx_atomic_int_t value, ngx_uint_t spin) { #if (NGX_HAVE_ATOMIC_OPS) - ngx_uint_t tries; - - tries = 0; + ngx_uint_t i, n; for ( ;; ) { - if (*lock) { - if (ngx_ncpu > 1 && tries++ < spin) { - continue; - } + if (*lock == 0 && ngx_atomic_cmp_set(lock, 0, value)) { + return; + } + + if (ngx_ncpu > 1) { + + for (n = 1; n < spin; n <<= 1) { - ngx_sched_yield(); - - tries = 0; + for (i = 0; i < n; i++) { + ngx_cpu_pause(); + } - } else { - if (ngx_atomic_cmp_set(lock, 0, 1)) { - return; + if (*lock == 0 && ngx_atomic_cmp_set(lock, 0, value)) { + return; + } } } + + ngx_sched_yield(); } #else diff --git a/src/event/ngx_event.c b/src/event/ngx_event.c --- a/src/event/ngx_event.c +++ b/src/event/ngx_event.c @@ -31,7 +31,6 @@ static char *ngx_event_debug_connection( static void *ngx_event_create_conf(ngx_cycle_t *cycle); static char *ngx_event_init_conf(ngx_cycle_t *cycle, void *conf); -static char *ngx_accept_mutex_check(ngx_conf_t *cf, void *post, void *data); static ngx_uint_t ngx_timer_resolution; @@ -48,7 +47,8 @@ ngx_atomic_t *ngx_connection_cou ngx_atomic_t *ngx_accept_mutex_ptr; -ngx_atomic_t *ngx_accept_mutex; +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; @@ -112,8 +112,6 @@ ngx_module_t ngx_events_module = { static ngx_str_t event_core_name = ngx_string("event_core"); -static ngx_conf_post_t ngx_accept_mutex_post = { ngx_accept_mutex_check } ; - static ngx_command_t ngx_event_core_commands[] = { @@ -150,7 +148,7 @@ static ngx_command_t ngx_event_core_com ngx_conf_set_flag_slot, 0, offsetof(ngx_event_conf_t, accept_mutex), - &ngx_accept_mutex_post }, + NULL }, { ngx_string("accept_mutex_delay"), NGX_EVENT_CONF|NGX_CONF_TAKE1, @@ -218,7 +216,7 @@ ngx_process_events_and_timers(ngx_cycle_ #endif } - if (ngx_accept_mutex) { + if (ngx_use_accept_mutex) { if (ngx_accept_disabled > 0) { ngx_accept_disabled--; @@ -254,7 +252,7 @@ ngx_process_events_and_timers(ngx_cycle_ } if (ngx_accept_mutex_held) { - (void) ngx_atomic_cmp_set(ngx_accept_mutex, ngx_pid, 0); + ngx_shmtx_unlock(&ngx_accept_mutex); } if (delta) { @@ -415,7 +413,7 @@ ngx_event_module_init(ngx_cycle_t *cycle { void ***cf; u_char *shared; - size_t size; + size_t size, cl; ngx_event_conf_t *ecf; ngx_core_conf_t *ccf; ngx_shm_t shm; @@ -465,24 +463,41 @@ ngx_event_module_init(ngx_cycle_t *cycle #endif /* !(NGX_WIN32) */ - if (ccf->master == 0 || ngx_accept_mutex_ptr) { + if (ccf->master == 0) { return NGX_OK; } - /* TODO: adjust cache line size, 128 is P4 cache line size */ + 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; + } - size = 128 /* ngx_accept_mutex */ - + 128; /* ngx_connection_counter */ + 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 += 128 /* ngx_stat_accepted */ - + 128 /* ngx_stat_handled */ - + 128 /* ngx_stat_requests */ - + 128 /* ngx_stat_active */ - + 128 /* ngx_stat_reading */ - + 128; /* ngx_stat_writing */ + 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 @@ -496,16 +511,24 @@ ngx_event_module_init(ngx_cycle_t *cycle shared = shm.addr; ngx_accept_mutex_ptr = (ngx_atomic_t *) shared; - ngx_connection_counter = (ngx_atomic_t *) (shared + 1 * 128); + + 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 * 128); - ngx_stat_handled = (ngx_atomic_t *) (shared + 3 * 128); - ngx_stat_requests = (ngx_atomic_t *) (shared + 4 * 128); - ngx_stat_active = (ngx_atomic_t *) (shared + 5 * 128); - ngx_stat_reading = (ngx_atomic_t *) (shared + 6 * 128); - ngx_stat_writing = (ngx_atomic_t *) (shared + 7 * 128); + 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 @@ -557,11 +580,13 @@ ngx_event_process_init(ngx_cycle_t *cycl 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 (ngx_accept_mutex_ptr && ccf->worker_processes > 1 && ecf->accept_mutex) - { - ngx_accept_mutex = ngx_accept_mutex_ptr; + 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) @@ -775,7 +800,7 @@ ngx_event_process_init(ngx_cycle_t *cycl rev->handler = ngx_event_accept; - if (ngx_accept_mutex) { + if (ngx_use_accept_mutex) { continue; } @@ -1221,22 +1246,3 @@ ngx_event_init_conf(ngx_cycle_t *cycle, #endif } - - -static char * -ngx_accept_mutex_check(ngx_conf_t *cf, void *post, void *data) -{ -#if !(NGX_HAVE_ATOMIC_OPS) - - ngx_flag_t *fp = data; - - *fp = 0; - - ngx_conf_log_error(NGX_LOG_WARN, cf, 0, - "\"accept_mutex\" is not supported on this platform, " - "ignored"); - -#endif - - return NGX_CONF_OK; -} diff --git a/src/event/ngx_event.h b/src/event/ngx_event.h --- a/src/event/ngx_event.h +++ b/src/event/ngx_event.h @@ -438,7 +438,8 @@ typedef struct { extern ngx_atomic_t *ngx_connection_counter; extern ngx_atomic_t *ngx_accept_mutex_ptr; -extern ngx_atomic_t *ngx_accept_mutex; +extern ngx_shmtx_t ngx_accept_mutex; +extern ngx_uint_t ngx_use_accept_mutex; extern ngx_uint_t ngx_accept_mutex_held; extern ngx_msec_t ngx_accept_mutex_delay; extern ngx_int_t ngx_accept_disabled; diff --git a/src/event/ngx_event_accept.c b/src/event/ngx_event_accept.c --- a/src/event/ngx_event_accept.c +++ b/src/event/ngx_event_accept.c @@ -259,9 +259,8 @@ ngx_event_accept(ngx_event_t *ev) ngx_int_t ngx_trylock_accept_mutex(ngx_cycle_t *cycle) { - if (*ngx_accept_mutex == 0 - && ngx_atomic_cmp_set(ngx_accept_mutex, 0, ngx_pid)) - { + if (ngx_shmtx_trylock(&ngx_accept_mutex)) { + ngx_log_debug0(NGX_LOG_DEBUG_EVENT, cycle->log, 0, "accept mutex locked"); @@ -271,7 +270,7 @@ ngx_trylock_accept_mutex(ngx_cycle_t *cy } if (ngx_enable_accept_events(cycle) == NGX_ERROR) { - *ngx_accept_mutex = 0; + ngx_shmtx_unlock(&ngx_accept_mutex); return NGX_ERROR; } diff --git a/src/event/ngx_event_openssl.c b/src/event/ngx_event_openssl.c --- a/src/event/ngx_event_openssl.c +++ b/src/event/ngx_event_openssl.c @@ -1009,6 +1009,20 @@ ngx_ssl_cleanup_ctx(void *data) } +u_char * +ngx_ssl_get_protocol(ngx_connection_t *c) +{ + return (u_char *) SSL_get_version(c->ssl->connection); +} + + +u_char * +ngx_ssl_get_cipher_name(ngx_connection_t *c) +{ + return (u_char *) SSL_get_cipher_name(c->ssl->connection); +} + + static void * ngx_openssl_create_conf(ngx_cycle_t *cycle) { diff --git a/src/event/ngx_event_openssl.h b/src/event/ngx_event_openssl.h --- a/src/event/ngx_event_openssl.h +++ b/src/event/ngx_event_openssl.h @@ -69,8 +69,13 @@ ngx_int_t ngx_ssl_create_connection(ngx_ ngx_uint_t flags); ngx_int_t ngx_ssl_set_session(ngx_connection_t *c, ngx_ssl_session_t *session); -#define ngx_ssl_get_session(c) SSL_get1_session(c->ssl->connection) -#define ngx_ssl_free_session SSL_SESSION_free +#define ngx_ssl_get_session(c) SSL_get1_session(c->ssl->connection) +#define ngx_ssl_free_session SSL_SESSION_free + + +u_char *ngx_ssl_get_protocol(ngx_connection_t *c); +u_char *ngx_ssl_get_cipher_name(ngx_connection_t *c); + ngx_int_t ngx_ssl_handshake(ngx_connection_t *c); ssize_t ngx_ssl_recv(ngx_connection_t *c, u_char *buf, size_t size); diff --git a/src/http/modules/ngx_http_proxy_module.c b/src/http/modules/ngx_http_proxy_module.c --- a/src/http/modules/ngx_http_proxy_module.c +++ b/src/http/modules/ngx_http_proxy_module.c @@ -741,6 +741,8 @@ ngx_http_proxy_create_request(ngx_http_r body = body->next; } + b->flush = 1; + } else { u->request_bufs = cl; } diff --git a/src/http/modules/ngx_http_referer_module.c b/src/http/modules/ngx_http_referer_module.c --- a/src/http/modules/ngx_http_referer_module.c +++ b/src/http/modules/ngx_http_referer_module.c @@ -271,6 +271,8 @@ ngx_http_referer_merge_conf(ngx_conf_t * conf->blocked_referer = 0; } + conf->keys = NULL; + return NGX_CONF_OK; } diff --git a/src/http/modules/ngx_http_ssi_filter_module.c b/src/http/modules/ngx_http_ssi_filter_module.c --- a/src/http/modules/ngx_http_ssi_filter_module.c +++ b/src/http/modules/ngx_http_ssi_filter_module.c @@ -29,6 +29,7 @@ typedef struct { typedef struct { ngx_str_t name; + ngx_uint_t key; ngx_str_t value; } ngx_http_ssi_var_t; @@ -62,7 +63,7 @@ static ngx_int_t ngx_http_ssi_output(ngx static ngx_int_t ngx_http_ssi_parse(ngx_http_request_t *r, ngx_http_ssi_ctx_t *ctx); static ngx_str_t *ngx_http_ssi_get_variable(ngx_http_request_t *r, - ngx_str_t *name); + ngx_str_t *name, ngx_uint_t key); static ngx_int_t ngx_http_ssi_evaluate_string(ngx_http_request_t *r, ngx_http_ssi_ctx_t *ctx, ngx_str_t *text, ngx_uint_t flags); @@ -1335,7 +1336,8 @@ ngx_http_ssi_parse(ngx_http_request_t *r static ngx_str_t * -ngx_http_ssi_get_variable(ngx_http_request_t *r, ngx_str_t *name) +ngx_http_ssi_get_variable(ngx_http_request_t *r, ngx_str_t *name, + ngx_uint_t key) { ngx_uint_t i; ngx_http_ssi_var_t *var; @@ -1349,7 +1351,11 @@ ngx_http_ssi_get_variable(ngx_http_reque continue; } - if (ngx_strncasecmp(name->data, var[i].name.data, name->len) == 0) { + if (key != var[i].key) { + continue; + } + + if (ngx_strncmp(name->data, var[i].name.data, name->len) == 0) { return &var[i].value; } } @@ -1365,6 +1371,7 @@ ngx_http_ssi_evaluate_string(ngx_http_re u_char ch, *p, **value, *data, *part_data; size_t *size, len, prefix, part_len; ngx_str_t var, *val; + ngx_int_t key; ngx_uint_t i, j, n, bracket; ngx_array_t lengths, values; ngx_http_variable_value_t *vv; @@ -1469,14 +1476,17 @@ ngx_http_ssi_evaluate_string(ngx_http_re goto invalid_variable; } + key = 0; + for (j = 0; j < var.len; j++) { var.data[j] = ngx_tolower(var.data[j]); + key = ngx_hash(key, var.data[j]); } - val = ngx_http_ssi_get_variable(r, &var); + val = ngx_http_ssi_get_variable(r, &var, key); if (val == NULL) { - vv = ngx_http_get_variable(r, &var); + vv = ngx_http_get_variable(r, &var, key); if (vv == NULL) { return NGX_ERROR; @@ -1636,6 +1646,7 @@ static ngx_int_t ngx_http_ssi_echo(ngx_http_request_t *r, ngx_http_ssi_ctx_t *ctx, ngx_str_t **params) { + ngx_int_t key; ngx_uint_t i; ngx_buf_t *b; ngx_str_t *var, *value, text; @@ -1644,14 +1655,17 @@ ngx_http_ssi_echo(ngx_http_request_t *r, var = params[NGX_HTTP_SSI_ECHO_VAR]; - value = ngx_http_ssi_get_variable(r, var); + key = 0; + + for (i = 0; i < var->len; i++) { + var->data[i] = ngx_tolower(var->data[i]); + key = ngx_hash(key, var->data[i]); + } + + value = ngx_http_ssi_get_variable(r, var, key); if (value == NULL) { - for (i = 0; i < var->len; i++) { - var->data[i] = ngx_tolower(var->data[i]); - } - - vv = ngx_http_get_variable(r, var); + vv = ngx_http_get_variable(r, var, key); if (vv == NULL) { return NGX_HTTP_SSI_ERROR; @@ -1735,6 +1749,8 @@ static ngx_int_t ngx_http_ssi_set(ngx_http_request_t *r, ngx_http_ssi_ctx_t *ctx, ngx_str_t **params) { + ngx_int_t key; + ngx_uint_t i; ngx_str_t *name, *value, *vv; ngx_http_ssi_var_t *var; ngx_http_ssi_ctx_t *mctx; @@ -1756,7 +1772,14 @@ ngx_http_ssi_set(ngx_http_request_t *r, return NGX_HTTP_SSI_ERROR; } - vv = ngx_http_ssi_get_variable(r, name); + key = 0; + + for (i = 0; i < name->len; i++) { + name->data[i] = ngx_tolower(name->data[i]); + key = ngx_hash(key, name->data[i]); + } + + vv = ngx_http_ssi_get_variable(r, name, key); if (vv) { *vv = *value; @@ -1769,6 +1792,7 @@ ngx_http_ssi_set(ngx_http_request_t *r, } var->name = *name; + var->key = key; var->value = *value; ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, diff --git a/src/http/modules/ngx_http_ssl_module.c b/src/http/modules/ngx_http_ssl_module.c --- a/src/http/modules/ngx_http_ssl_module.c +++ b/src/http/modules/ngx_http_ssl_module.c @@ -9,11 +9,18 @@ #include +typedef u_char *(*ngx_ssl_variable_handler_pt)(ngx_connection_t *); + + #define NGX_DEFLAUT_CERTIFICATE "cert.pem" #define NGX_DEFLAUT_CERTIFICATE_KEY "cert.pem" #define NGX_DEFLAUT_CIPHERS "ALL:!ADH:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv2:+EXP" +static ngx_int_t ngx_http_ssl_variable(ngx_http_request_t *r, + ngx_http_variable_value_t *v, uintptr_t data); + +static ngx_int_t ngx_http_ssl_add_variables(ngx_conf_t *cf); static void *ngx_http_ssl_create_srv_conf(ngx_conf_t *cf); static char *ngx_http_ssl_merge_srv_conf(ngx_conf_t *cf, void *parent, void *child); @@ -97,7 +104,7 @@ static ngx_command_t ngx_http_ssl_comma static ngx_http_module_t ngx_http_ssl_module_ctx = { - NULL, /* preconfiguration */ + ngx_http_ssl_add_variables, /* preconfiguration */ NULL, /* postconfiguration */ NULL, /* create main configuration */ @@ -127,9 +134,70 @@ ngx_module_t ngx_http_ssl_module = { }; +static ngx_http_variable_t ngx_http_ssl_vars[] = { + + { ngx_string("ssl_protocol"), ngx_http_ssl_variable, + (uintptr_t) ngx_ssl_get_protocol, NGX_HTTP_VAR_CHANGABLE, 0 }, + + { ngx_string("ssl_cipher"), ngx_http_ssl_variable, + (uintptr_t) ngx_ssl_get_cipher_name, NGX_HTTP_VAR_CHANGABLE, 0 }, + + { ngx_null_string, NULL, 0, 0, 0 } +}; + + static u_char ngx_http_session_id_ctx[] = "HTTP"; +static ngx_int_t +ngx_http_ssl_variable(ngx_http_request_t *r, + ngx_http_variable_value_t *v, uintptr_t data) +{ + ngx_ssl_variable_handler_pt handler = (ngx_ssl_variable_handler_pt) data; + + size_t len; + u_char *name; + + if (r->connection->ssl) { + + name = handler(r->connection); + + for (len = 0; name[len]; len++) { /* void */ } + + v->len = len; + v->valid = 1; + v->no_cachable = 0; + v->not_found = 0; + v->data = name; + + return NGX_OK; + } + + v->not_found = 1; + + return NGX_OK; +} + + +static ngx_int_t +ngx_http_ssl_add_variables(ngx_conf_t *cf) +{ + ngx_http_variable_t *var, *v; + + for (v = ngx_http_ssl_vars; v->name.len; v++) { + var = ngx_http_add_variable(cf, &v->name, v->flags); + if (var == NULL) { + return NGX_ERROR; + } + + var->handler = v->handler; + var->data = v->data; + } + + return NGX_OK; +} + + static void * ngx_http_ssl_create_srv_conf(ngx_conf_t *cf) { diff --git a/src/http/ngx_http_core_module.c b/src/http/ngx_http_core_module.c --- a/src/http/ngx_http_core_module.c +++ b/src/http/ngx_http_core_module.c @@ -77,6 +77,20 @@ static ngx_conf_enum_t ngx_http_restric static ngx_command_t ngx_http_core_commands[] = { + { ngx_string("variables_hash_max_size"), + NGX_HTTP_MAIN_CONF|NGX_CONF_TAKE1, + ngx_conf_set_num_slot, + NGX_HTTP_MAIN_CONF_OFFSET, + offsetof(ngx_http_core_main_conf_t, variables_hash_max_size), + NULL }, + + { ngx_string("variables_hash_bucket_size"), + NGX_HTTP_MAIN_CONF|NGX_CONF_TAKE1, + ngx_conf_set_num_slot, + NGX_HTTP_MAIN_CONF_OFFSET, + offsetof(ngx_http_core_main_conf_t, variables_hash_bucket_size), + NULL }, + { ngx_string("server_names_hash_max_size"), NGX_HTTP_MAIN_CONF|NGX_CONF_TAKE1, ngx_conf_set_num_slot, @@ -1787,6 +1801,9 @@ ngx_http_core_create_main_conf(ngx_conf_ cmcf->server_names_hash_max_size = NGX_CONF_UNSET_UINT; cmcf->server_names_hash_bucket_size = NGX_CONF_UNSET_UINT; + cmcf->variables_hash_max_size = NGX_CONF_UNSET_UINT; + cmcf->variables_hash_bucket_size = NGX_CONF_UNSET_UINT; + return cmcf; } @@ -1807,6 +1824,18 @@ ngx_http_core_init_main_conf(ngx_conf_t cmcf->server_names_hash_bucket_size = ngx_align(cmcf->server_names_hash_bucket_size, ngx_cacheline_size); + + if (cmcf->variables_hash_max_size == NGX_CONF_UNSET_UINT) { + cmcf->variables_hash_max_size = 512; + } + + if (cmcf->variables_hash_bucket_size == NGX_CONF_UNSET_UINT) { + cmcf->variables_hash_bucket_size = 64; + } + + cmcf->variables_hash_bucket_size = + ngx_align(cmcf->variables_hash_bucket_size, ngx_cacheline_size); + return NGX_CONF_OK; } @@ -2224,7 +2253,7 @@ ngx_http_core_listen(ngx_conf_t *cf, ngx ls->family = AF_INET; ls->port = (in_port_t) (inet_upstream.default_port ? - 80 : inet_upstream.port); + 80 : inet_upstream.port); ls->file_name = cf->conf_file->file.name; ls->line = cf->conf_file->line; ls->conf.backlog = -1; diff --git a/src/http/ngx_http_core_module.h b/src/http/ngx_http_core_module.h --- a/src/http/ngx_http_core_module.h +++ b/src/http/ngx_http_core_module.h @@ -71,13 +71,18 @@ typedef struct { ngx_http_phase_t phases[NGX_HTTP_LOG_PHASE + 1]; ngx_hash0_t headers_in_hash; - ngx_hash0_t variables_hash; + + ngx_hash_t variables_hash; + + ngx_array_t variables; /* ngx_http_variable_t */ ngx_uint_t server_names_hash_max_size; ngx_uint_t server_names_hash_bucket_size; - ngx_array_t variables; /* ngx_http_variable_t */ - ngx_array_t all_variables; /* ngx_http_variable_t */ + ngx_uint_t variables_hash_max_size; + ngx_uint_t variables_hash_bucket_size; + + ngx_hash_keys_arrays_t *variables_keys; } ngx_http_core_main_conf_t; diff --git a/src/http/ngx_http_request.c b/src/http/ngx_http_request.c --- a/src/http/ngx_http_request.c +++ b/src/http/ngx_http_request.c @@ -174,7 +174,7 @@ ngx_http_init_connection(ngx_connection_ if (rev->ready) { /* the deferred accept(), rtsig, aio, iocp */ - if (ngx_accept_mutex) { + if (ngx_use_accept_mutex) { ngx_post_event(rev, &ngx_posted_events); return; } diff --git a/src/http/ngx_http_upstream.c b/src/http/ngx_http_upstream.c --- a/src/http/ngx_http_upstream.c +++ b/src/http/ngx_http_upstream.c @@ -1457,11 +1457,10 @@ ngx_http_upstream_process_non_buffered_b if (ev->timedout) { if (ev->write) { c->timedout = 1; - ngx_log_error(NGX_LOG_ERR, c->log, NGX_ETIMEDOUT, - "client timed out"); + ngx_connection_error(c, NGX_ETIMEDOUT, "client timed out"); + } else { - ngx_log_error(NGX_LOG_ERR, c->log, NGX_ETIMEDOUT, - "upstream timed out"); + ngx_connection_error(c, NGX_ETIMEDOUT, "upstream timed out"); } } @@ -1681,14 +1680,12 @@ ngx_http_upstream_process_body(ngx_event } else { p->downstream_error = 1; c->timedout = 1; - ngx_log_error(NGX_LOG_ERR, c->log, NGX_ETIMEDOUT, - "client timed out"); + ngx_connection_error(c, NGX_ETIMEDOUT, "client timed out"); } } else { p->upstream_error = 1; - ngx_log_error(NGX_LOG_ERR, c->log, NGX_ETIMEDOUT, - "upstream timed out"); + ngx_connection_error(c, NGX_ETIMEDOUT, "upstream timed out"); } } else { diff --git a/src/http/ngx_http_variables.c b/src/http/ngx_http_variables.c --- a/src/http/ngx_http_variables.c +++ b/src/http/ngx_http_variables.c @@ -42,6 +42,8 @@ static ngx_int_t ngx_http_variable_reque ngx_http_variable_value_t *v, uintptr_t data); static ngx_int_t ngx_http_variable_remote_user(ngx_http_request_t *r, ngx_http_variable_value_t *v, uintptr_t data); +static ngx_int_t ngx_http_variable_body_bytes_sent(ngx_http_request_t *r, + ngx_http_variable_value_t *v, uintptr_t data); /* @@ -130,6 +132,9 @@ static ngx_http_variable_t ngx_http_cor { ngx_string("remote_user"), ngx_http_variable_remote_user, 0, 0, 0 }, + { ngx_string("body_bytes_sent"), ngx_http_variable_body_bytes_sent, + 0, 0, 0 }, + { ngx_null_string, NULL, 0, 0, 0 } }; @@ -143,30 +148,34 @@ ngx_http_variable_value_t ngx_http_vari ngx_http_variable_t * ngx_http_add_variable(ngx_conf_t *cf, ngx_str_t *name, ngx_uint_t flags) { + ngx_int_t rc; ngx_uint_t i; + ngx_hash_key_t *key; ngx_http_variable_t *v; ngx_http_core_main_conf_t *cmcf; cmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_core_module); - v = cmcf->all_variables.elts; - for (i = 0; i < cmcf->all_variables.nelts; i++) { - if (name->len != v[i].name.len - || ngx_strncasecmp(name->data, v[i].name.data, name->len) != 0) + key = cmcf->variables_keys->keys.elts; + for (i = 0; i < cmcf->variables_keys->keys.nelts; i++) { + if (name->len != key[i].key.len + || ngx_strncasecmp(name->data, key[i].key.data, name->len) != 0) { continue; } - if (!(v[i].flags & NGX_HTTP_VAR_CHANGABLE)) { + v = key[i].value; + + if (!(v->flags & NGX_HTTP_VAR_CHANGABLE)) { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "the duplicate \"%V\" variable", name); return NULL; } - return &v[i]; + return v; } - v = ngx_array_push(&cmcf->all_variables); + v = ngx_palloc(cf->pool, sizeof(ngx_http_variable_t)); if (v == NULL) { return NULL; } @@ -186,6 +195,18 @@ ngx_http_add_variable(ngx_conf_t *cf, ng v->flags = flags; v->index = 0; + rc = ngx_hash_add_key(cmcf->variables_keys, &v->name, v, 0); + + if (rc == NGX_ERROR) { + return NULL; + } + + if (rc == NGX_BUSY) { + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, + "conflicting variable name \"%V\"", name); + return NULL; + } + return v; } @@ -298,34 +319,25 @@ ngx_http_get_flushed_variable(ngx_http_r ngx_http_variable_value_t * -ngx_http_get_variable(ngx_http_request_t *r, ngx_str_t *name) +ngx_http_get_variable(ngx_http_request_t *r, ngx_str_t *name, ngx_uint_t key) { - ngx_uint_t i, key; ngx_http_variable_t *v; ngx_http_variable_value_t *vv; ngx_http_core_main_conf_t *cmcf; cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module); - key = 0; - for (i = 0; i < name->len; i++) { - key += name->data[i]; - } + v = ngx_hash_find(&cmcf->variables_hash, key, name->data, name->len); - key %= cmcf->variables_hash.hash_size; - v = (ngx_http_variable_t *) cmcf->variables_hash.buckets; - - if (v[key].name.len == name->len - && ngx_strncmp(v[key].name.data, name->data, name->len) == 0) - { - if (v[key].flags & NGX_HTTP_VAR_INDEXED) { - return ngx_http_get_indexed_variable(r, v[key].index); + if (v) { + if (v->flags & NGX_HTTP_VAR_INDEXED) { + return ngx_http_get_indexed_variable(r, v->index); } else { vv = ngx_palloc(r->pool, sizeof(ngx_http_variable_value_t)); - if (vv && v[key].handler(r, vv, v[key].data) == NGX_OK) { + if (vv && v->handler(r, vv, v->data) == NGX_OK) { return vv; } @@ -758,28 +770,72 @@ ngx_http_variable_remote_user(ngx_http_r } +static ngx_int_t +ngx_http_variable_body_bytes_sent(ngx_http_request_t *r, + ngx_http_variable_value_t *v, uintptr_t data) +{ + off_t sent; + u_char *p; + + sent = r->connection->sent - r->header_size; + + if (sent < 0) { + sent = 0; + } + + p = ngx_palloc(r->pool, NGX_OFF_T_LEN); + if (p == NULL) { + return NGX_ERROR; + } + + v->len = ngx_sprintf(p, "%O", sent) - p; + v->valid = 1; + v->no_cachable = 0; + v->not_found = 0; + v->data = p; + + return NGX_OK; +} + + ngx_int_t ngx_http_variables_add_core_vars(ngx_conf_t *cf) { - ngx_http_variable_t *v, *cv; + ngx_int_t rc; + ngx_http_variable_t *v; ngx_http_core_main_conf_t *cmcf; cmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_core_module); - if (ngx_array_init(&cmcf->all_variables, cf->pool, 32, - sizeof(ngx_http_variable_t)) - == NGX_ERROR) + cmcf->variables_keys = ngx_pcalloc(cf->temp_pool, + sizeof(ngx_hash_keys_arrays_t)); + if (cmcf->variables_keys == NULL) { + return NGX_ERROR; + } + + cmcf->variables_keys->pool = cf->pool; + cmcf->variables_keys->temp_pool = cf->pool; + + if (ngx_hash_keys_array_init(cmcf->variables_keys, NGX_HASH_SMALL) + != NGX_OK) { return NGX_ERROR; } - for (cv = ngx_http_core_variables; cv->name.len; cv++) { - v = ngx_array_push(&cmcf->all_variables); - if (v == NULL) { - return NGX_ERROR; + for (v = ngx_http_core_variables; v->name.len; v++) { + rc = ngx_hash_add_key(cmcf->variables_keys, &v->name, v, + NGX_HASH_READONLY_KEY); + + if (rc == NGX_OK) { + continue; } - *v = *cv; + if (rc == NGX_BUSY) { + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, + "conflicting variable name \"%V\"", &v->name); + } + + return NGX_ERROR; } return NGX_OK; @@ -790,6 +846,8 @@ ngx_int_t ngx_http_variables_init_vars(ngx_conf_t *cf) { ngx_uint_t i, n; + ngx_hash_key_t *key; + ngx_hash_init_t hash; ngx_http_variable_t *v, *av; ngx_http_core_main_conf_t *cmcf; @@ -798,23 +856,25 @@ ngx_http_variables_init_vars(ngx_conf_t cmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_core_module); v = cmcf->variables.elts; - av = cmcf->all_variables.elts; + key = cmcf->variables_keys->keys.elts; for (i = 0; i < cmcf->variables.nelts; i++) { - for (n = 0; n < cmcf->all_variables.nelts; n++) { + for (n = 0; n < cmcf->variables_keys->keys.nelts; n++) { - if (v[i].name.len == av[n].name.len - && ngx_strncmp(v[i].name.data, av[n].name.data, v[i].name.len) + if (v[i].name.len == key[n].key.len + && ngx_strncmp(v[i].name.data, key[n].key.data, v[i].name.len) == 0) { - v[i].handler = av[n].handler; - v[i].data = av[n].data; + av = key[n].value; + + v[i].handler = av->handler; + v[i].data = av->data; - av[n].flags |= NGX_HTTP_VAR_INDEXED; - v[i].flags = av[n].flags; + av->flags |= NGX_HTTP_VAR_INDEXED; + v[i].flags = av->flags; - av[n].index = i; + av->index = i; goto next; } @@ -843,36 +903,32 @@ ngx_http_variables_init_vars(ngx_conf_t continue; } - ngx_log_debug1(NGX_LOG_DEBUG_HTTP, cf->log, 0, - "http variables: %ui", cmcf->variables.nelts); - - for (n = 0; n < cmcf->all_variables.nelts; n++) { - if (av[n].flags & NGX_HTTP_VAR_NOHASH) { - av[n].name.data = NULL; + for (n = 0; n < cmcf->variables_keys->keys.nelts; n++) { + av = key[n].value; + + if (av->flags & NGX_HTTP_VAR_NOHASH) { + key[n].key.data = NULL; } } - /* init the all http variables hash */ + hash.hash = &cmcf->variables_hash; + hash.key = ngx_hash_key; + hash.max_size = cmcf->variables_hash_max_size; + hash.bucket_size = cmcf->variables_hash_bucket_size; + hash.name = "variables_hash"; + hash.pool = cf->pool; + hash.temp_pool = NULL; - cmcf->variables_hash.max_size = 500; - cmcf->variables_hash.bucket_limit = 1; - cmcf->variables_hash.bucket_size = sizeof(ngx_http_variable_t); - cmcf->variables_hash.name = "http variables"; - - if (ngx_hash0_init(&cmcf->variables_hash, cf->pool, - cmcf->all_variables.elts, cmcf->all_variables.nelts) + if (ngx_hash_init(&hash, cmcf->variables_keys->keys.elts, + cmcf->variables_keys->keys.nelts) != NGX_OK) { return NGX_ERROR; } - ngx_log_debug3(NGX_LOG_DEBUG_HTTP, cf->log, 0, - "http variables hash size: %ui for %ui values, " - "max buckets per entry: %ui", - cmcf->variables_hash.hash_size, cmcf->all_variables.nelts, - cmcf->variables_hash.min_buckets); + cmcf->variables_keys = NULL; return NGX_OK; } diff --git a/src/http/ngx_http_variables.h b/src/http/ngx_http_variables.h --- a/src/http/ngx_http_variables.h +++ b/src/http/ngx_http_variables.h @@ -56,7 +56,7 @@ ngx_http_variable_value_t *ngx_http_get_ ngx_uint_t index); ngx_http_variable_value_t *ngx_http_get_variable(ngx_http_request_t *r, - ngx_str_t *name); + ngx_str_t *name, ngx_uint_t key); #define ngx_http_clear_variable(r, index) r->variables0[index].text.data = NULL; diff --git a/src/os/unix/ngx_atomic.h b/src/os/unix/ngx_atomic.h --- a/src/os/unix/ngx_atomic.h +++ b/src/os/unix/ngx_atomic.h @@ -34,6 +34,7 @@ ngx_atomic_fetch_add(ngx_atomic_t *value /* the code in src/os/unix/ngx_sunpro_x86.il */ #define ngx_memory_barrier() __asm (".volatile"); __asm (".nonvolatile") +#define ngx_cpu_pause() __asm ("pause") #else /* ( __GNUC__ || __INTEL_COMPILER ) */ @@ -67,6 +68,7 @@ ngx_atomic_fetch_add(ngx_atomic_t *value /* the code in src/os/unix/ngx_sunpro_amd64.il */ #define ngx_memory_barrier() __asm (".volatile"); __asm (".nonvolatile") +#define ngx_cpu_pause() __asm ("pause") #else /* ( __GNUC__ || __INTEL_COMPILER ) */ @@ -175,10 +177,11 @@ ngx_atomic_fetch_add(ngx_atomic_t *value } #define ngx_memory_barrier() +#define ngx_cpu_pause() #endif -void ngx_spinlock(ngx_atomic_t *lock, ngx_uint_t spin); +void ngx_spinlock(ngx_atomic_t *lock, ngx_atomic_int_t value, ngx_uint_t spin); #define ngx_trylock(lock) (*(lock) == 0 && ngx_atomic_cmp_set(lock, 0, 1)) #define ngx_unlock(lock) *(lock) = 0 diff --git a/src/os/unix/ngx_files.c b/src/os/unix/ngx_files.c --- a/src/os/unix/ngx_files.c +++ b/src/os/unix/ngx_files.c @@ -235,59 +235,58 @@ ngx_open_dir(ngx_str_t *name, ngx_dir_t } -ngx_int_t -ngx_lock_file(ngx_file_t *file) +ngx_err_t +ngx_trylock_fd(ngx_fd_t fd) { - ngx_err_t err; struct flock fl; + fl.l_start = 0; + fl.l_len = 0; + fl.l_pid = 0; + fl.l_type = F_WRLCK; fl.l_whence = SEEK_SET; + + if (fcntl(fd, F_SETLK, &fl) == -1) { + return ngx_errno; + } + + return 0; +} + + +ngx_err_t +ngx_lock_fd(ngx_fd_t fd) +{ + struct flock fl; + + fl.l_start = 0; fl.l_len = 0; fl.l_pid = 0; fl.l_type = F_WRLCK; - fl.l_start = 0; - - if (fcntl(file->fd, F_SETLK, &fl) == -1) { - err = ngx_errno; + fl.l_whence = SEEK_SET; - if (err == NGX_EAGAIN) { - return NGX_BUSY; - } - - ngx_log_error(NGX_LOG_ALERT, file->log, err, - "fcntl(%s, F_SETLK, F_WRLCK) failed", file->name.data); - - return NGX_ERROR; + if (fcntl(fd, F_SETLKW, &fl) == -1) { + return ngx_errno; } - return NGX_OK; + return 0; } -ngx_int_t -ngx_unlock_file(ngx_file_t *file) +ngx_err_t +ngx_unlock_fd(ngx_fd_t fd) { - ngx_err_t err; struct flock fl; - fl.l_whence = SEEK_SET; + fl.l_start = 0; fl.l_len = 0; fl.l_pid = 0; fl.l_type = F_UNLCK; - fl.l_start = 0; - - if (fcntl(file->fd, F_SETLK, &fl) == -1) { - err = ngx_errno; + fl.l_whence = SEEK_SET; - if (err == NGX_EAGAIN) { - return NGX_BUSY; - } - - ngx_log_error(NGX_LOG_ALERT, file->log, err, - "fcntl(%s, F_SETLK, F_UNLCK) failed", file->name.data); - - return NGX_ERROR; + if (fcntl(fd, F_SETLK, &fl) == -1) { + return ngx_errno; } - return NGX_OK; + return 0; } diff --git a/src/os/unix/ngx_files.h b/src/os/unix/ngx_files.h --- a/src/os/unix/ngx_files.h +++ b/src/os/unix/ngx_files.h @@ -119,4 +119,13 @@ ngx_int_t ngx_open_dir(ngx_str_t *name, #define ngx_de_mtime(dir) (dir)->info.st_mtime +ngx_err_t ngx_trylock_fd(ngx_fd_t fd); +ngx_err_t ngx_lock_fd(ngx_fd_t fd); +ngx_err_t ngx_unlock_fd(ngx_fd_t fd); + +#define ngx_trylock_fd_n "fcntl(F_SETLK, F_WRLCK)" +#define ngx_lock_fd_n "fcntl(F_SETLKW, F_WRLCK)" +#define ngx_unlock_fd_n "fcntl(F_SETLK, F_UNLCK)" + + #endif /* _NGX_FILES_H_INCLUDED_ */ diff --git a/src/os/unix/ngx_gcc_atomic_amd64.h b/src/os/unix/ngx_gcc_atomic_amd64.h --- a/src/os/unix/ngx_gcc_atomic_amd64.h +++ b/src/os/unix/ngx_gcc_atomic_amd64.h @@ -74,4 +74,6 @@ ngx_atomic_fetch_add(ngx_atomic_t *value } -#define ngx_memory_barrier() __asm__ volatile ("" ::: "memory") +#define ngx_memory_barrier() __asm__ volatile ("" ::: "memory") + +#define ngx_cpu_pause() __asm__ ("pause") diff --git a/src/os/unix/ngx_gcc_atomic_ppc.h b/src/os/unix/ngx_gcc_atomic_ppc.h --- a/src/os/unix/ngx_gcc_atomic_ppc.h +++ b/src/os/unix/ngx_gcc_atomic_ppc.h @@ -71,3 +71,5 @@ ngx_atomic_fetch_add(ngx_atomic_t *value #else #define ngx_memory_barrier() __asm__ volatile ("" ::: "memory") #endif + +#define ngx_cpu_pause() diff --git a/src/os/unix/ngx_gcc_atomic_sparc64.h b/src/os/unix/ngx_gcc_atomic_sparc64.h --- a/src/os/unix/ngx_gcc_atomic_sparc64.h +++ b/src/os/unix/ngx_gcc_atomic_sparc64.h @@ -77,3 +77,5 @@ ngx_atomic_fetch_add(ngx_atomic_t *value #else #define ngx_memory_barrier() __asm__ volatile ("" ::: "memory") #endif + +#define ngx_cpu_pause() diff --git a/src/os/unix/ngx_gcc_atomic_x86.h b/src/os/unix/ngx_gcc_atomic_x86.h --- a/src/os/unix/ngx_gcc_atomic_x86.h +++ b/src/os/unix/ngx_gcc_atomic_x86.h @@ -118,3 +118,6 @@ ngx_atomic_fetch_add(ngx_atomic_t *value */ #define ngx_memory_barrier() __asm__ volatile ("" ::: "memory") + +/* old as does not support "pause" opcode */ +#define ngx_cpu_pause() __asm__ (".byte 0xf3, 0x90") diff --git a/src/os/unix/ngx_posix_init.c b/src/os/unix/ngx_posix_init.c --- a/src/os/unix/ngx_posix_init.c +++ b/src/os/unix/ngx_posix_init.c @@ -45,6 +45,8 @@ ngx_os_init(ngx_log_t *log) ngx_ncpu = 1; } + ngx_cpuinfo(); + if (getrlimit(RLIMIT_NOFILE, &rlmt) == -1) { ngx_log_error(NGX_LOG_ALERT, log, errno, "getrlimit(RLIMIT_NOFILE) failed)"); diff --git a/src/os/unix/ngx_sunpro_atomic_sparc64.h b/src/os/unix/ngx_sunpro_atomic_sparc64.h --- a/src/os/unix/ngx_sunpro_atomic_sparc64.h +++ b/src/os/unix/ngx_sunpro_atomic_sparc64.h @@ -56,3 +56,5 @@ ngx_atomic_fetch_add(ngx_atomic_t *value __asm (".volatile"); \ __asm ("membar #LoadLoad | #LoadStore | #StoreStore | #StoreLoad"); \ __asm (".nonvolatile") + +#define ngx_cpu_pause()