# HG changeset patch # User Igor Sysoev # Date 1280260800 -14400 # Node ID cde3626b2d0d4a784d9d33b41640672fa66ae24d # Parent 5de4f69bbbab8c4e2f5bb08934bd284c4bee770c nginx 0.8.47 *) Bugfix: $request_time variable had invalid values for subrequests. *) Bugfix: errors intercepted by error_page could be cached. *) Bugfix: a cache manager process my got caught in an endless loop, if max_size parameter was used; the bug had appeared in 0.8.46. diff --git a/CHANGES b/CHANGES --- a/CHANGES +++ b/CHANGES @@ -1,12 +1,22 @@ +Changes with nginx 0.8.47 28 Jul 2010 + + *) Bugfix: $request_time variable had invalid values for subrequests. + + *) Bugfix: errors intercepted by error_page could be cached. + + *) Bugfix: a cache manager process my got caught in an endless loop, if + max_size parameter was used; the bug had appeared in 0.8.46. + + Changes with nginx 0.8.46 19 Jul 2010 *) Change: now the "proxy_no_cache", "fastcgi_no_cache", - "uwsgi_no_cache", and "sсgi_no_cache" directives affect on a cached + "uwsgi_no_cache", and "scgi_no_cache" directives affect on a cached response saving only. *) Feature: the "proxy_cache_bypass", "fastcgi_cache_bypass", - "uwsgi_cache_bypass", and "sсgi_cache_bypass" directives. + "uwsgi_cache_bypass", and "scgi_cache_bypass" directives. *) Bugfix: nginx did not free memory in cache keys zones if there was an error during working with backend: the memory was freed only diff --git a/CHANGES.ru b/CHANGES.ru --- a/CHANGES.ru +++ b/CHANGES.ru @@ -1,12 +1,23 @@ +Изменения в nginx 0.8.47 28.07.2010 + + *) Исправление: переменная $request_time имела неверные значения для + подзапросов. + + *) Исправление: ошибки, перехваченные error_page, не кэшировались. + + *) Исправление: если использовался параметр max_size, то cache manager + мог зациклиться. ошибка появилась в 0.8.46. + + Изменения в nginx 0.8.46 19.07.2010 *) Изменение: директивы proxy_no_cache, fastcgi_no_cache, - uwsgi_no_cache и sсgi_no_cache теперь влияют только на сохранение + uwsgi_no_cache и scgi_no_cache теперь влияют только на сохранение закэшированного ответа. *) Добавление: директивы proxy_cache_bypass, fastcgi_cache_bypass, - uwsgi_cache_bypass и sсgi_cache_bypass. + uwsgi_cache_bypass и scgi_cache_bypass. *) Исправление: nginx не освобождал память в keys_zone кэшей в случае ошибки работы с бэкендом: память освобождалась только по истечении diff --git a/src/core/nginx.h b/src/core/nginx.h --- a/src/core/nginx.h +++ b/src/core/nginx.h @@ -8,8 +8,8 @@ #define _NGINX_H_INCLUDED_ -#define nginx_version 8046 -#define NGINX_VERSION "0.8.46" +#define nginx_version 8047 +#define NGINX_VERSION "0.8.47" #define NGINX_VER "nginx/" NGINX_VERSION #define NGINX_VAR "NGINX" diff --git a/src/http/modules/perl/nginx.pm b/src/http/modules/perl/nginx.pm --- a/src/http/modules/perl/nginx.pm +++ b/src/http/modules/perl/nginx.pm @@ -48,7 +48,7 @@ our @EXPORT = qw( HTTP_INSUFFICIENT_STORAGE ); -our $VERSION = '0.8.46'; +our $VERSION = '0.8.47'; require XSLoader; XSLoader::load('nginx', $VERSION); diff --git a/src/http/ngx_http_cache.h b/src/http/ngx_http_cache.h --- a/src/http/ngx_http_cache.h +++ b/src/http/ngx_http_cache.h @@ -78,6 +78,7 @@ struct ngx_http_cache_s { ngx_http_file_cache_node_t *node; unsigned updated:1; + unsigned updating:1; unsigned exists:1; unsigned temp_file:1; }; @@ -129,7 +130,7 @@ ngx_int_t ngx_http_file_cache_open(ngx_h void 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); ngx_int_t ngx_http_cache_send(ngx_http_request_t *); -void ngx_http_file_cache_free(ngx_http_request_t *r, ngx_temp_file_t *tf); +void ngx_http_file_cache_free(ngx_http_cache_t *c, ngx_temp_file_t *tf); time_t ngx_http_file_cache_valid(ngx_array_t *cache_valid, ngx_uint_t status); char *ngx_http_file_cache_set_slot(ngx_conf_t *cf, ngx_command_t *cmd, 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 @@ -2152,6 +2152,7 @@ ngx_http_subrequest(ngx_http_request_t * ngx_str_t *uri, ngx_str_t *args, ngx_http_request_t **psr, ngx_http_post_subrequest_t *ps, ngx_uint_t flags) { + ngx_time_t *tp; ngx_connection_t *c; ngx_http_request_t *sr; ngx_http_core_srv_conf_t *cscf; @@ -2264,6 +2265,10 @@ ngx_http_subrequest(ngx_http_request_t * sr->uri_changes = NGX_HTTP_MAX_URI_CHANGES + 1; + tp = ngx_timeofday(); + r->start_sec = tp->sec; + r->start_msec = tp->msec; + r->main->subrequests++; r->main->count++; diff --git a/src/http/ngx_http_file_cache.c b/src/http/ngx_http_file_cache.c --- a/src/http/ngx_http_file_cache.c +++ b/src/http/ngx_http_file_cache.c @@ -161,6 +161,7 @@ ngx_http_file_cache_new(ngx_http_request r->cache = c; c->file.log = r->connection->log; + c->file.fd = NGX_INVALID_FILE; return NGX_OK; } @@ -429,6 +430,7 @@ ngx_http_file_cache_read(ngx_http_reques } else { c->node->updating = 1; + c->updating = 1; rc = NGX_HTTP_CACHE_STALE; } @@ -792,6 +794,7 @@ ngx_http_file_cache_update(ngx_http_requ "http file cache update"); c->updated = 1; + c->updating = 0; cache = c->file_cache; @@ -901,37 +904,35 @@ ngx_http_cache_send(ngx_http_request_t * void -ngx_http_file_cache_free(ngx_http_request_t *r, ngx_temp_file_t *tf) +ngx_http_file_cache_free(ngx_http_cache_t *c, ngx_temp_file_t *tf) { - ngx_http_cache_t *c; ngx_http_file_cache_t *cache; ngx_http_file_cache_node_t *fcn; - c = r->cache; - if (c->updated) { return; } - c->updated = 1; - cache = c->file_cache; - ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, - "http file cache free"); + ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->file.log, 0, + "http file cache free, fd: %d", c->file.fd); ngx_shmtx_lock(&cache->shpool->mutex); fcn = c->node; fcn->count--; - fcn->updating = 0; + + if (c->updating) { + fcn->updating = 0; + } if (c->error) { fcn->valid_sec = c->valid_sec; fcn->valid_msec = c->valid_msec; fcn->error = c->error; - } else if (fcn->valid_msec == 0 && fcn->count == 0) { + } else if (!fcn->exists && fcn->count == 0) { ngx_queue_remove(&fcn->queue); ngx_rbtree_delete(&cache->sh->rbtree, &fcn->node); ngx_slab_free_locked(cache->shpool, fcn); @@ -940,14 +941,17 @@ ngx_http_file_cache_free(ngx_http_reques ngx_shmtx_unlock(&cache->shpool->mutex); + c->updated = 1; + c->updating = 0; + if (c->temp_file) { if (tf && tf->file.fd != NGX_INVALID_FILE) { - ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, + ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->file.log, 0, "http file cache incomplete: \"%s\"", tf->file.name.data); if (ngx_delete_file(tf->file.name.data) == NGX_FILE_ERROR) { - ngx_log_error(NGX_LOG_CRIT, r->connection->log, ngx_errno, + ngx_log_error(NGX_LOG_CRIT, c->file.log, ngx_errno, ngx_delete_file_n " \"%s\" failed", tf->file.name.data); } @@ -961,28 +965,19 @@ ngx_http_file_cache_cleanup(void *data) { ngx_http_cache_t *c = data; - ngx_http_file_cache_t *cache; - if (c->updated) { return; } - c->updated = 1; - ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->file.log, 0, "http file cache cleanup"); - if (c->error) { - return; + if (c->updating) { + ngx_log_error(NGX_LOG_ALERT, c->file.log, 0, + "stalled cache updating, error:%ui", c->error); } - cache = c->file_cache; - - ngx_shmtx_lock(&cache->shpool->mutex); - - c->node->count--; - - ngx_shmtx_unlock(&cache->shpool->mutex); + ngx_http_file_cache_free(c, NULL); } 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 @@ -1720,6 +1720,21 @@ ngx_http_upstream_intercept_errors(ngx_h r->headers_out.www_authenticate = h; } +#if (NGX_HTTP_CACHE) + + if (r->cache) { + time_t valid; + + valid = ngx_http_file_cache_valid(u->conf->cache_valid, status); + + if (valid) { + r->cache->valid_sec = ngx_time() + valid; + r->cache->error = status; + } + + ngx_http_file_cache_free(r->cache, u->pipe->temp_file); + } +#endif ngx_http_upstream_finalize_request(r, u, status); return NGX_OK; @@ -1933,7 +1948,7 @@ ngx_http_upstream_process_body_in_memory if (size == 0) { ngx_log_error(NGX_LOG_ALERT, c->log, 0, - "upstream buffer is too small to read repsonse"); + "upstream buffer is too small to read response"); ngx_http_upstream_finalize_request(r, u, NGX_ERROR); return; } @@ -2171,7 +2186,7 @@ ngx_http_upstream_send_response(ngx_http "http cacheable: %d", u->cacheable); if (u->cacheable == 0 && r->cache) { - ngx_http_file_cache_free(r, u->pipe->temp_file); + ngx_http_file_cache_free(r->cache, u->pipe->temp_file); } #endif @@ -2646,7 +2661,7 @@ ngx_http_upstream_process_request(ngx_ht ngx_http_file_cache_update(r, u->pipe->temp_file); } else if (p->upstream_error) { - ngx_http_file_cache_free(r, u->pipe->temp_file); + ngx_http_file_cache_free(r->cache, u->pipe->temp_file); } } @@ -2974,10 +2989,6 @@ ngx_http_upstream_finalize_request(ngx_h if (u->cacheable && r->cache) { time_t valid; - ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, - "http upstream cache fd: %d", - r->cache->file.fd); - if (rc == NGX_HTTP_BAD_GATEWAY || rc == NGX_HTTP_GATEWAY_TIME_OUT) { valid = ngx_http_file_cache_valid(u->conf->cache_valid, rc); @@ -2988,7 +2999,7 @@ ngx_http_upstream_finalize_request(ngx_h } } - ngx_http_file_cache_free(r, u->pipe->temp_file); + ngx_http_file_cache_free(r->cache, u->pipe->temp_file); } #endif