diff options
author | nginx <nginx@nginx.org> | 2015-02-10 14:44:22 +0000 |
---|---|---|
committer | Jon Kolb <kolbyjack@gmail.com> | 2015-02-10 14:44:22 +0000 |
commit | aa248e453fd0df9623d5da0f13727049e69e503d (patch) | |
tree | 32fb764b530f7c8d6441efd814ab7d8a2142a7d2 | |
parent | fb7c9d545bae32ef766515b88b98a5133db86230 (diff) | |
download | nginx-aa248e453fd0df9623d5da0f13727049e69e503d.tar.gz |
Changes with nginx 1.7.10 10 Feb 2015v1.7.10
*) Feature: the "use_temp_path" parameter of the "proxy_cache_path",
"fastcgi_cache_path", "scgi_cache_path", and "uwsgi_cache_path"
directives.
*) Feature: the $upstream_header_time variable.
*) Workaround: now on disk overflow nginx tries to write error logs once
a second only.
*) Bugfix: the "try_files" directive did not ignore normal files while
testing directories.
Thanks to Damien Tournoud.
*) Bugfix: alerts "sendfile() failed" if the "sendfile" directive was
used on OS X; the bug had appeared in 1.7.8.
*) Bugfix: alerts "sem_post() failed" might appear in logs.
*) Bugfix: nginx could not be built with musl libc.
Thanks to James Taylor.
*) Bugfix: nginx could not be built on Tru64 UNIX.
Thanks to Goetz T. Fischer.
-rw-r--r-- | CHANGES | 27 | ||||
-rw-r--r-- | CHANGES.ru | 26 | ||||
-rw-r--r-- | LICENSE | 4 | ||||
-rw-r--r-- | src/core/nginx.h | 4 | ||||
-rw-r--r-- | src/core/ngx_file.c | 12 | ||||
-rw-r--r-- | src/core/ngx_log.c | 25 | ||||
-rw-r--r-- | src/core/ngx_log.h | 2 | ||||
-rw-r--r-- | src/core/ngx_output_chain.c | 8 | ||||
-rw-r--r-- | src/core/ngx_shmtx.c | 5 | ||||
-rw-r--r-- | src/core/ngx_string.c | 6 | ||||
-rw-r--r-- | src/http/ngx_http_cache.h | 3 | ||||
-rw-r--r-- | src/http/ngx_http_core_module.c | 2 | ||||
-rw-r--r-- | src/http/ngx_http_file_cache.c | 164 | ||||
-rw-r--r-- | src/http/ngx_http_upstream.c | 35 | ||||
-rw-r--r-- | src/http/ngx_http_upstream.h | 2 | ||||
-rw-r--r-- | src/os/unix/ngx_darwin_sendfile_chain.c | 3 | ||||
-rw-r--r-- | src/os/unix/ngx_user.c | 2 |
17 files changed, 273 insertions, 57 deletions
@@ -1,4 +1,31 @@ +Changes with nginx 1.7.10 10 Feb 2015 + + *) Feature: the "use_temp_path" parameter of the "proxy_cache_path", + "fastcgi_cache_path", "scgi_cache_path", and "uwsgi_cache_path" + directives. + + *) Feature: the $upstream_header_time variable. + + *) Workaround: now on disk overflow nginx tries to write error logs once + a second only. + + *) Bugfix: the "try_files" directive did not ignore normal files while + testing directories. + Thanks to Damien Tournoud. + + *) Bugfix: alerts "sendfile() failed" if the "sendfile" directive was + used on OS X; the bug had appeared in 1.7.8. + + *) Bugfix: alerts "sem_post() failed" might appear in logs. + + *) Bugfix: nginx could not be built with musl libc. + Thanks to James Taylor. + + *) Bugfix: nginx could not be built on Tru64 UNIX. + Thanks to Goetz T. Fischer. + + Changes with nginx 1.7.9 23 Dec 2014 *) Feature: variables support in the "proxy_cache", "fastcgi_cache", diff --git a/CHANGES.ru b/CHANGES.ru index 7ba7aa79c..abb909b2e 100644 --- a/CHANGES.ru +++ b/CHANGES.ru @@ -1,4 +1,30 @@ +Изменения в nginx 1.7.10 10.02.2015 + + *) Добавление: параметр use_temp_path директив proxy_cache_path, + fastcgi_cache_path, scgi_cache_path и uwsgi_cache_path. + + *) Добавление: переменная $upstream_header_time. + + *) Изменение: теперь при переполнении диска nginx пытается писать + error_log'и только раз в секунду. + + *) Исправление: директива try_files при тестировании каталогов не + игнорировала обычные файлы. + Спасибо Damien Tournoud. + + *) Исправление: при использовании директивы sendfile на OS X возникали + ошибки "sendfile() failed"; ошибка появилась в nginx 1.7.8. + + *) Исправление: в лог могли писаться сообщения "sem_post() failed". + + *) Исправление: nginx не собирался с musl libc. + Спасибо James Taylor. + + *) Исправление: nginx не собирался на Tru64 UNIX. + Спасибо Goetz T. Fischer. + + Изменения в nginx 1.7.9 23.12.2014 *) Добавление: директивы proxy_cache, fastcgi_cache, scgi_cache и @@ -1,6 +1,6 @@ /* - * Copyright (C) 2002-2014 Igor Sysoev - * Copyright (C) 2011-2014 Nginx, Inc. + * Copyright (C) 2002-2015 Igor Sysoev + * Copyright (C) 2011-2015 Nginx, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/src/core/nginx.h b/src/core/nginx.h index 4c4b8e404..93dc82d64 100644 --- a/src/core/nginx.h +++ b/src/core/nginx.h @@ -9,8 +9,8 @@ #define _NGINX_H_INCLUDED_ -#define nginx_version 1007009 -#define NGINX_VERSION "1.7.9" +#define nginx_version 1007010 +#define NGINX_VERSION "1.7.10" #define NGINX_VER "nginx/" NGINX_VERSION #ifdef NGX_BUILD diff --git a/src/core/ngx_file.c b/src/core/ngx_file.c index 7e6e921a3..ae2373511 100644 --- a/src/core/ngx_file.c +++ b/src/core/ngx_file.c @@ -114,7 +114,7 @@ ngx_write_chain_to_temp_file(ngx_temp_file_t *tf, ngx_chain_t *chain) rc = ngx_create_temp_file(&tf->file, tf->path, tf->pool, tf->persistent, tf->clean, tf->access); - if (rc == NGX_ERROR || rc == NGX_AGAIN) { + if (rc != NGX_OK) { return rc; } @@ -1035,10 +1035,18 @@ ngx_walk_tree(ngx_tree_ctx_t *ctx, ngx_str_t *tree) ctx->access = ngx_de_access(&dir); ctx->mtime = ngx_de_mtime(&dir); - if (ctx->pre_tree_handler(ctx, &file) == NGX_ABORT) { + rc = ctx->pre_tree_handler(ctx, &file); + + if (rc == NGX_ABORT) { goto failed; } + if (rc == NGX_DECLINED) { + ngx_log_debug1(NGX_LOG_DEBUG_CORE, ctx->log, 0, + "tree skip dir \"%s\"", file.data); + continue; + } + if (ngx_walk_tree(ctx, &file) == NGX_ABORT) { goto failed; } diff --git a/src/core/ngx_log.c b/src/core/ngx_log.c index 005d9ff88..0cf235998 100644 --- a/src/core/ngx_log.c +++ b/src/core/ngx_log.c @@ -91,8 +91,9 @@ ngx_log_error_core(ngx_uint_t level, ngx_log_t *log, ngx_err_t err, va_list args; #endif u_char *p, *last, *msg; - u_char errstr[NGX_MAX_ERROR_STR]; + ssize_t n; ngx_uint_t wrote_stderr, debug_connection; + u_char errstr[NGX_MAX_ERROR_STR]; last = errstr + NGX_MAX_ERROR_STR; @@ -150,16 +151,32 @@ ngx_log_error_core(ngx_uint_t level, ngx_log_t *log, ngx_err_t err, if (log->writer) { log->writer(log, level, errstr, p - errstr); - log = log->next; - continue; + goto next; } - (void) ngx_write_fd(log->file->fd, errstr, p - errstr); + if (ngx_time() == log->disk_full_time) { + + /* + * on FreeBSD writing to a full filesystem with enabled softupdates + * may block process for much longer time than writing to non-full + * filesystem, so we skip writing to a log for one second + */ + + goto next; + } + + n = ngx_write_fd(log->file->fd, errstr, p - errstr); + + if (n == -1 && ngx_errno == NGX_ENOSPC) { + log->disk_full_time = ngx_time(); + } if (log->file->fd == ngx_stderr) { wrote_stderr = 1; } + next: + log = log->next; } diff --git a/src/core/ngx_log.h b/src/core/ngx_log.h index 95ecca528..6b04b7876 100644 --- a/src/core/ngx_log.h +++ b/src/core/ngx_log.h @@ -53,6 +53,8 @@ struct ngx_log_s { ngx_atomic_uint_t connection; + time_t disk_full_time; + ngx_log_handler_pt handler; void *data; diff --git a/src/core/ngx_output_chain.c b/src/core/ngx_output_chain.c index 3cb60ea73..9d7a8460f 100644 --- a/src/core/ngx_output_chain.c +++ b/src/core/ngx_output_chain.c @@ -45,8 +45,12 @@ ngx_output_chain(ngx_output_chain_ctx_t *ctx, ngx_chain_t *in) ngx_int_t rc, last; ngx_chain_t *cl, *out, **last_out; - if (ctx->in == NULL && ctx->busy == NULL) { - + if (ctx->in == NULL && ctx->busy == NULL +#if (NGX_HAVE_FILE_AIO) + && !ctx->aio +#endif + ) + { /* * the short path for the case when the ctx->in and ctx->busy chains * are empty, the incoming chain is empty too or has the single buf diff --git a/src/core/ngx_shmtx.c b/src/core/ngx_shmtx.c index a62999f33..a255903ef 100644 --- a/src/core/ngx_shmtx.c +++ b/src/core/ngx_shmtx.c @@ -101,6 +101,7 @@ ngx_shmtx_lock(ngx_shmtx_t *mtx) (void) ngx_atomic_fetch_add(mtx->wait, 1); if (*mtx->lock == 0 && ngx_atomic_cmp_set(mtx->lock, 0, ngx_pid)) { + (void) ngx_atomic_fetch_add(mtx->wait, -1); return; } @@ -174,7 +175,7 @@ ngx_shmtx_wakeup(ngx_shmtx_t *mtx) wait = *mtx->wait; - if (wait == 0) { + if ((ngx_atomic_int_t) wait <= 0) { return; } @@ -258,7 +259,7 @@ ngx_shmtx_trylock(ngx_shmtx_t *mtx) #if __osf__ /* Tru64 UNIX */ - if (err == NGX_EACCESS) { + if (err == NGX_EACCES) { return 0; } diff --git a/src/core/ngx_string.c b/src/core/ngx_string.c index a41c38d37..f8641b7ab 100644 --- a/src/core/ngx_string.c +++ b/src/core/ngx_string.c @@ -429,8 +429,12 @@ ngx_vslprintf(u_char *buf, u_char *last, const char *fmt, va_list args) case 'N': #if (NGX_WIN32) *buf++ = CR; -#endif + if (buf < last) { + *buf++ = LF; + } +#else *buf++ = LF; +#endif fmt++; continue; diff --git a/src/http/ngx_http_cache.h b/src/http/ngx_http_cache.h index 033882e53..a7d41c6f1 100644 --- a/src/http/ngx_http_cache.h +++ b/src/http/ngx_http_cache.h @@ -142,6 +142,7 @@ struct ngx_http_file_cache_s { ngx_slab_pool_t *shpool; ngx_path_t *path; + ngx_path_t *temp_path; off_t max_size; size_t bsize; @@ -162,7 +163,7 @@ ngx_int_t ngx_http_file_cache_new(ngx_http_request_t *r); ngx_int_t ngx_http_file_cache_create(ngx_http_request_t *r); void ngx_http_file_cache_create_key(ngx_http_request_t *r); ngx_int_t ngx_http_file_cache_open(ngx_http_request_t *r); -void ngx_http_file_cache_set_header(ngx_http_request_t *r, u_char *buf); +ngx_int_t ngx_http_file_cache_set_header(ngx_http_request_t *r, u_char *buf); void ngx_http_file_cache_update(ngx_http_request_t *r, ngx_temp_file_t *tf); void ngx_http_file_cache_update_header(ngx_http_request_t *r); ngx_int_t ngx_http_cache_send(ngx_http_request_t *); diff --git a/src/http/ngx_http_core_module.c b/src/http/ngx_http_core_module.c index d8ff53bfe..0542b2871 100644 --- a/src/http/ngx_http_core_module.c +++ b/src/http/ngx_http_core_module.c @@ -1353,7 +1353,7 @@ ngx_http_core_try_files_phase(ngx_http_request_t *r, continue; } - if (of.is_dir && !test_dir) { + if (of.is_dir != test_dir) { continue; } diff --git a/src/http/ngx_http_file_cache.c b/src/http/ngx_http_file_cache.c index 681c913c6..00d4c0f5a 100644 --- a/src/http/ngx_http_file_cache.c +++ b/src/http/ngx_http_file_cache.c @@ -37,6 +37,8 @@ static void ngx_http_file_cache_vary_header(ngx_http_request_t *r, ngx_md5_t *md5, ngx_str_t *name); static ngx_int_t ngx_http_file_cache_reopen(ngx_http_request_t *r, ngx_http_cache_t *c); +static ngx_int_t ngx_http_file_cache_update_variant(ngx_http_request_t *r, + ngx_http_cache_t *c); static void ngx_http_file_cache_cleanup(void *data); static time_t ngx_http_file_cache_forced_expire(ngx_http_file_cache_t *cache); static time_t ngx_http_file_cache_expire(ngx_http_file_cache_t *cache); @@ -47,6 +49,8 @@ static ngx_int_t ngx_http_file_cache_noop(ngx_tree_ctx_t *ctx, ngx_str_t *path); static ngx_int_t ngx_http_file_cache_manage_file(ngx_tree_ctx_t *ctx, ngx_str_t *path); +static ngx_int_t ngx_http_file_cache_manage_directory(ngx_tree_ctx_t *ctx, + ngx_str_t *path); static ngx_int_t ngx_http_file_cache_add_file(ngx_tree_ctx_t *ctx, ngx_str_t *path); static ngx_int_t ngx_http_file_cache_add(ngx_http_file_cache_t *cache, @@ -1122,7 +1126,7 @@ ngx_http_file_cache_reopen(ngx_http_request_t *r, ngx_http_cache_t *c) } -void +ngx_int_t ngx_http_file_cache_set_header(ngx_http_request_t *r, u_char *buf) { ngx_http_file_cache_header_t *h = (ngx_http_file_cache_header_t *) buf; @@ -1164,9 +1168,10 @@ ngx_http_file_cache_set_header(ngx_http_request_t *r, u_char *buf) ngx_http_file_cache_vary(r, c->vary.data, c->vary.len, c->variant); ngx_memcpy(h->variant, c->variant, NGX_HTTP_CACHE_KEY_LEN); + } - } else { - ngx_memzero(c->variant, NGX_HTTP_CACHE_KEY_LEN); + if (ngx_http_file_cache_update_variant(r, c) != NGX_OK) { + return NGX_ERROR; } p = buf + sizeof(ngx_http_file_cache_header_t); @@ -1179,6 +1184,57 @@ ngx_http_file_cache_set_header(ngx_http_request_t *r, u_char *buf) } *p = LF; + + return NGX_OK; +} + + +static ngx_int_t +ngx_http_file_cache_update_variant(ngx_http_request_t *r, ngx_http_cache_t *c) +{ + ngx_http_file_cache_t *cache; + + if (!c->secondary) { + return NGX_OK; + } + + if (c->vary.len + && ngx_memcmp(c->variant, c->key, NGX_HTTP_CACHE_KEY_LEN) == 0) + { + return NGX_OK; + } + + /* + * if the variant hash doesn't match one we used as a secondary + * cache key, switch back to the original key + */ + + cache = c->file_cache; + + ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, + "http file cache main key"); + + ngx_shmtx_lock(&cache->shpool->mutex); + + c->node->count--; + c->node->updating = 0; + c->node = NULL; + + ngx_shmtx_unlock(&cache->shpool->mutex); + + c->file.name.len = 0; + + ngx_memcpy(c->key, c->main, NGX_HTTP_CACHE_KEY_LEN); + + if (ngx_http_file_cache_exists(cache, c) == NGX_ERROR) { + return NGX_ERROR; + } + + if (ngx_http_file_cache_name(r, cache->path) != NGX_OK) { + return NGX_ERROR; + } + + return NGX_OK; } @@ -1204,38 +1260,6 @@ ngx_http_file_cache_update(ngx_http_request_t *r, ngx_temp_file_t *tf) cache = c->file_cache; - if (c->secondary - && ngx_memcmp(c->variant, c->key, NGX_HTTP_CACHE_KEY_LEN) != 0) - { - /* - * if the variant hash doesn't match one we used as a secondary - * cache key, switch back to the original key - */ - - ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, - "http file cache main key"); - - ngx_shmtx_lock(&cache->shpool->mutex); - - c->node->count--; - c->node->updating = 0; - c->node = NULL; - - ngx_shmtx_unlock(&cache->shpool->mutex); - - c->file.name.len = 0; - - ngx_memcpy(c->key, c->main, NGX_HTTP_CACHE_KEY_LEN); - - if (ngx_http_file_cache_exists(cache, c) == NGX_ERROR) { - return; - } - - if (ngx_http_file_cache_name(r, cache->path) != NGX_OK) { - return; - } - } - c->updated = 1; c->updating = 0; @@ -1823,7 +1847,7 @@ ngx_http_file_cache_loader(void *data) tree.init_handler = NULL; tree.file_handler = ngx_http_file_cache_manage_file; - tree.pre_tree_handler = ngx_http_file_cache_noop; + tree.pre_tree_handler = ngx_http_file_cache_manage_directory; tree.post_tree_handler = ngx_http_file_cache_noop; tree.spec_handler = ngx_http_file_cache_delete_file; tree.data = cache; @@ -1888,6 +1912,19 @@ ngx_http_file_cache_manage_file(ngx_tree_ctx_t *ctx, ngx_str_t *path) } +static ngx_int_t +ngx_http_file_cache_manage_directory(ngx_tree_ctx_t *ctx, ngx_str_t *path) +{ + if (path->len >= 5 + && ngx_strncmp(path->data + path->len - 5, "/temp", 5) == 0) + { + return NGX_DECLINED; + } + + return NGX_OK; +} + + static void ngx_http_file_cache_loader_sleep(ngx_http_file_cache_t *cache) { @@ -2037,11 +2074,12 @@ ngx_http_file_cache_set_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) off_t max_size; u_char *last, *p; time_t inactive; + size_t len; ssize_t size; ngx_str_t s, name, *value; ngx_int_t loader_files; ngx_msec_t loader_sleep, loader_threshold; - ngx_uint_t i, n; + ngx_uint_t i, n, use_temp_path; ngx_array_t *caches; ngx_http_file_cache_t *cache, **ce; @@ -2055,6 +2093,8 @@ ngx_http_file_cache_set_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) return NGX_CONF_ERROR; } + use_temp_path = 1; + inactive = 600; loader_files = 100; loader_sleep = 50; @@ -2115,6 +2155,25 @@ ngx_http_file_cache_set_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) return NGX_CONF_ERROR; } + if (ngx_strncmp(value[i].data, "use_temp_path=", 14) == 0) { + + if (ngx_strcmp(&value[i].data[14], "on") == 0) { + use_temp_path = 1; + + } else if (ngx_strcmp(&value[i].data[14], "off") == 0) { + use_temp_path = 0; + + } else { + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, + "invalid use_temp_path value \"%V\", " + "it must be \"on\" or \"off\"", + &value[i]); + return NGX_CONF_ERROR; + } + + continue; + } + if (ngx_strncmp(value[i].data, "keys_zone=", 10) == 0) { name.data = value[i].data + 10; @@ -2237,6 +2296,37 @@ ngx_http_file_cache_set_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) return NGX_CONF_ERROR; } + if (!use_temp_path) { + cache->temp_path = ngx_pcalloc(cf->pool, sizeof(ngx_path_t)); + if (cache->temp_path == NULL) { + return NGX_CONF_ERROR; + } + + len = cache->path->name.len + sizeof("/temp") - 1; + + p = ngx_pnalloc(cf->pool, len + 1); + if (p == NULL) { + return NGX_CONF_ERROR; + } + + cache->temp_path->name.len = len; + cache->temp_path->name.data = p; + + p = ngx_cpymem(p, cache->path->name.data, cache->path->name.len); + ngx_memcpy(p, "/temp", sizeof("/temp")); + + ngx_memcpy(&cache->temp_path->level, &cache->path->level, + 3 * sizeof(size_t)); + + cache->temp_path->len = cache->path->len; + cache->temp_path->conf_file = cf->conf_file->file.name.data; + cache->temp_path->line = cf->conf_file->line; + + if (ngx_add_path(cf, &cache->temp_path) != NGX_OK) { + return NGX_CONF_ERROR; + } + } + cache->shm_zone = ngx_shared_memory_add(cf, &name, size, cmd->post); if (cache->shm_zone == NULL) { return NGX_CONF_ERROR; diff --git a/src/http/ngx_http_upstream.c b/src/http/ngx_http_upstream.c index c9a998001..a41d5b377 100644 --- a/src/http/ngx_http_upstream.c +++ b/src/http/ngx_http_upstream.c @@ -359,6 +359,10 @@ static ngx_http_variable_t ngx_http_upstream_vars[] = { ngx_http_upstream_status_variable, 0, NGX_HTTP_VAR_NOCACHEABLE, 0 }, + { ngx_string("upstream_header_time"), NULL, + ngx_http_upstream_response_time_variable, 1, + NGX_HTTP_VAR_NOCACHEABLE, 0 }, + { ngx_string("upstream_response_time"), NULL, ngx_http_upstream_response_time_variable, 0, NGX_HTTP_VAR_NOCACHEABLE, 0 }, @@ -1315,6 +1319,7 @@ ngx_http_upstream_connect(ngx_http_request_t *r, ngx_http_upstream_t *u) tp = ngx_timeofday(); u->state->response_sec = tp->sec; u->state->response_msec = tp->msec; + u->state->header_sec = (time_t) NGX_ERROR; rc = ngx_event_connect_peer(&u->peer); @@ -1836,6 +1841,7 @@ ngx_http_upstream_process_header(ngx_http_request_t *r, ngx_http_upstream_t *u) { ssize_t n; ngx_int_t rc; + ngx_time_t *tp; ngx_connection_t *c; c = u->peer.connection; @@ -1956,6 +1962,10 @@ ngx_http_upstream_process_header(ngx_http_request_t *r, ngx_http_upstream_t *u) /* rc == NGX_OK */ + tp = ngx_timeofday(); + u->state->header_sec = tp->sec - u->state->response_sec; + u->state->header_msec = tp->msec - u->state->response_msec; + if (u->headers_in.status_n >= NGX_HTTP_SPECIAL_RESPONSE) { if (ngx_http_upstream_test_next(r, u) == NGX_OK) { @@ -2628,7 +2638,10 @@ ngx_http_upstream_send_response(ngx_http_request_t *r, ngx_http_upstream_t *u) } } - ngx_http_file_cache_set_header(r, u->buffer.start); + if (ngx_http_file_cache_set_header(r, u->buffer.start) != NGX_OK) { + ngx_http_upstream_finalize_request(r, u, NGX_ERROR); + return; + } } else { u->cacheable = 0; @@ -2674,6 +2687,12 @@ ngx_http_upstream_send_response(ngx_http_request_t *r, ngx_http_upstream_t *u) if (p->cacheable) { p->temp_file->persistent = 1; +#if (NGX_HTTP_CACHE) + if (r->cache && r->cache->file_cache->temp_path) { + p->temp_file->path = r->cache->file_cache->temp_path; + } +#endif + } else { p->temp_file->log_level = NGX_LOG_WARN; p->temp_file->warn = "an upstream response is buffered " @@ -4811,8 +4830,18 @@ ngx_http_upstream_response_time_variable(ngx_http_request_t *r, for ( ;; ) { if (state[i].status) { - ms = (ngx_msec_int_t) - (state[i].response_sec * 1000 + state[i].response_msec); + + if (data + && state[i].header_sec != (time_t) NGX_ERROR) + { + ms = (ngx_msec_int_t) + (state[i].header_sec * 1000 + state[i].header_msec); + + } else { + ms = (ngx_msec_int_t) + (state[i].response_sec * 1000 + state[i].response_msec); + } + ms = ngx_max(ms, 0); p = ngx_sprintf(p, "%T.%03M", (time_t) ms / 1000, ms % 1000); diff --git a/src/http/ngx_http_upstream.h b/src/http/ngx_http_upstream.h index 9d2ec9345..98d7267b5 100644 --- a/src/http/ngx_http_upstream.h +++ b/src/http/ngx_http_upstream.h @@ -60,6 +60,8 @@ typedef struct { ngx_uint_t status; time_t response_sec; ngx_uint_t response_msec; + time_t header_sec; + ngx_uint_t header_msec; off_t response_length; ngx_str_t *peer; diff --git a/src/os/unix/ngx_darwin_sendfile_chain.c b/src/os/unix/ngx_darwin_sendfile_chain.c index f01651a11..c802e9f9a 100644 --- a/src/os/unix/ngx_darwin_sendfile_chain.c +++ b/src/os/unix/ngx_darwin_sendfile_chain.c @@ -111,6 +111,9 @@ ngx_darwin_sendfile_chain(ngx_connection_t *c, ngx_chain_t *in, off_t limit) } send += trailer.size; + + } else { + trailer.count = 0; } /* diff --git a/src/os/unix/ngx_user.c b/src/os/unix/ngx_user.c index 7a71203cb..3491f1c9e 100644 --- a/src/os/unix/ngx_user.c +++ b/src/os/unix/ngx_user.c @@ -31,8 +31,10 @@ ngx_libc_crypt(ngx_pool_t *pool, u_char *key, u_char *salt, u_char **encrypted) struct crypt_data cd; cd.initialized = 0; +#ifdef __GLIBC__ /* work around the glibc bug */ cd.current_salt[0] = ~salt[0]; +#endif value = crypt_r((char *) key, (char *) salt, &cd); |