summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authornginx <nginx@nginx.org>2015-02-10 14:44:22 +0000
committerJon Kolb <kolbyjack@gmail.com>2015-02-10 14:44:22 +0000
commitaa248e453fd0df9623d5da0f13727049e69e503d (patch)
tree32fb764b530f7c8d6441efd814ab7d8a2142a7d2
parentfb7c9d545bae32ef766515b88b98a5133db86230 (diff)
downloadnginx-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--CHANGES27
-rw-r--r--CHANGES.ru26
-rw-r--r--LICENSE4
-rw-r--r--src/core/nginx.h4
-rw-r--r--src/core/ngx_file.c12
-rw-r--r--src/core/ngx_log.c25
-rw-r--r--src/core/ngx_log.h2
-rw-r--r--src/core/ngx_output_chain.c8
-rw-r--r--src/core/ngx_shmtx.c5
-rw-r--r--src/core/ngx_string.c6
-rw-r--r--src/http/ngx_http_cache.h3
-rw-r--r--src/http/ngx_http_core_module.c2
-rw-r--r--src/http/ngx_http_file_cache.c164
-rw-r--r--src/http/ngx_http_upstream.c35
-rw-r--r--src/http/ngx_http_upstream.h2
-rw-r--r--src/os/unix/ngx_darwin_sendfile_chain.c3
-rw-r--r--src/os/unix/ngx_user.c2
17 files changed, 273 insertions, 57 deletions
diff --git a/CHANGES b/CHANGES
index 9932ca0b4..1170db637 100644
--- a/CHANGES
+++ b/CHANGES
@@ -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 и
diff --git a/LICENSE b/LICENSE
index 4ed7a6fc7..f75230800 100644
--- a/LICENSE
+++ b/LICENSE
@@ -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);