nginx-0.8.53 segfault

Maxim Dounin mdounin at mdounin.ru
Thu Jan 20 02:24:08 MSK 2011


Hello!

On Fri, Jan 14, 2011 at 09:55:35PM +0300, Maxim Dounin wrote:

> Hello!
> 
> On Fri, Jan 14, 2011 at 06:15:50PM +0100, Maxim C. wrote:
> 
> > Maxim, thanks for your help. I saved fresh core :) to anothe directory 
> > and ran gdb, output of the commands that you provided is:
> > 
> > (gdb) fr 0
> > #0  0x080aaca8 in ngx_http_file_cache_update (r=0x8200528, tf=0x8201570) 
> > at src/http/ngx_http_file_cache.c:790
> > 790      if (c->updated) {
> > (gdb) p c
> > $1 = (ngx_http_cache_t *) 0x0
> > (gdb) p *r
> > $2 = {signature = 1347703880, connection = 0x8133e88, ctx = 0x82009d8, 
> 
> [...]
> 
> >   http_version = 1001, request_line = {len = 30, data = 0x81fbfa8 "GET 
> > /preview/x045.jpg HTTP/1.1\r\nHost"}, uri = {len = 6, data = 0x8113d6c 
> > "/empty"},
> 
> [...]
> 
> > filter_finalize = 1, post_action = 0, request_complete = 0, 
> 
> Ah, understood, it's image filter which triggers the problem.  I'm 
> able to reproduce the problem here with the following config:
> 
>     server {
>         listen 127.0.0.1:8080;
> 
>         location / {
>             proxy_pass http://127.0.0.1:8080/bad/;
>             proxy_cache one;
>             proxy_cache_valid any 1h;
> 
>             image_filter   resize  150 100;
>             error_page     415   = /empty;
>         }
> 
>         location /empty {
>             return 204;
>         }
> 
>         location /bad/ {
>             return 404;
>         }
>     }
> 
> Right now I think correct solution would be to move r->cache into 
> upstream's private data (r->upstream).  Igor?

The attached patch moves r->cache into r->upstream (and resolves 
the SIGSEGV in question).

To Igor:

The patch is rather big and touches lots of code.  I would like to 
get some explicit response on it to avoid unneeded merge work.

Maxim Dounin
-------------- next part --------------
# HG changeset patch
# User Maxim Dounin <mdounin at mdounin.ru>
# Date 1295478387 -10800
# Node ID 16ed85edee18140cdf2c199d723daf4cba0815fd
# Parent  861939dcbd212e535cbee15c574a76bd7a72917a
Move r->cache to r->upstream to avoid conflicts.

1. Get rid of r->cache/r->cached dependencies in range filter, use correct
   offset calculations instead.

2. Change cache interfaces to accept cache object instead of unconditionally
   using r->cache one.

3. Move r->cache to r->upstream (mostly mechanical change of r->cache and
   r->cached to u->cache/cached or r->upstream->cache/cached as appropriate).

This allows upstream to assume cache isn't changed out of it's control (in
particular, invariant "u->cache != NULL if u->cacheable set" is preserved).
This should also simplify cache usage in other modules and allow multiple
caches to be used in parallel (e.g. one cache in upstream, another one in
some filter module).

This resolves problem with image_filter and proxy_cache, see here:

http://nginx.org/pipermail/nginx/2011-January/024703.html

Note that some problems may still be here in case of request finalization by
filter as upstream module with cache/store ignores downstream errors and
tries to continue work assuming r->upstream is still here.  This results
in undefined behaviour if another upstream request is issued during filter
finalization.

diff --git a/src/http/modules/ngx_http_fastcgi_module.c b/src/http/modules/ngx_http_fastcgi_module.c
--- a/src/http/modules/ngx_http_fastcgi_module.c
+++ b/src/http/modules/ngx_http_fastcgi_module.c
@@ -672,7 +672,7 @@ ngx_http_fastcgi_create_key(ngx_http_req
     ngx_str_t                    *key;
     ngx_http_fastcgi_loc_conf_t  *flcf;
 
-    key = ngx_array_push(&r->cache->keys);
+    key = ngx_array_push(&r->upstream->cache->keys);
     if (key == NULL) {
         return NGX_ERROR;
     }
@@ -1274,9 +1274,9 @@ ngx_http_fastcgi_process_header(ngx_http
                          */
 
 #if (NGX_HTTP_CACHE)
-                        if (r->cache) {
+                        if (u->cache) {
                             u->buffer.pos = u->buffer.start
-                                                     + r->cache->header_start;
+                                                     + u->cache->header_start;
                         } else {
                             u->buffer.pos = u->buffer.start;
                         }
@@ -1303,12 +1303,12 @@ ngx_http_fastcgi_process_header(ngx_http
 
 #if (NGX_HTTP_CACHE)
 
-        if (f->large_stderr && r->cache) {
+        if (f->large_stderr && u->cache) {
             u_char                     *start;
             ssize_t                     len;
             ngx_http_fastcgi_header_t  *fh;
 
-            start = u->buffer.start + r->cache->header_start;
+            start = u->buffer.start + u->cache->header_start;
 
             len = u->buffer.pos - start - 2 * sizeof(ngx_http_fastcgi_header_t);
 
@@ -1316,7 +1316,7 @@ ngx_http_fastcgi_process_header(ngx_http
              * A tail of large stderr output before HTTP header is placed
              * in a cache file without a FastCGI record header.
              * To workaround it we put a dummy FastCGI record header at the
-             * start of the stderr output or update r->cache_header_start,
+             * start of the stderr output or update u->cache_header_start,
              * if there is no enough place for the record header.
              */
 
@@ -1332,7 +1332,7 @@ ngx_http_fastcgi_process_header(ngx_http
                 fh->reserved = 0;
 
             } else {
-                r->cache->header_start += u->buffer.pos - start
+                u->cache->header_start += u->buffer.pos - start
                                            - sizeof(ngx_http_fastcgi_header_t);
             }
 
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
@@ -747,7 +747,7 @@ ngx_http_proxy_create_key(ngx_http_reque
 
     ctx = ngx_http_get_module_ctx(r, ngx_http_proxy_module);
 
-    key = ngx_array_push(&r->cache->keys);
+    key = ngx_array_push(&u->cache->keys);
     if (key == NULL) {
         return NGX_ERROR;
     }
@@ -763,7 +763,7 @@ ngx_http_proxy_create_key(ngx_http_reque
 
     *key = ctx->vars.key_start;
 
-    key = ngx_array_push(&r->cache->keys);
+    key = ngx_array_push(&u->cache->keys);
     if (key == NULL) {
         return NGX_ERROR;
     }
@@ -1191,7 +1191,7 @@ ngx_http_proxy_process_status_line(ngx_h
 
 #if (NGX_HTTP_CACHE)
 
-        if (r->cache) {
+        if (u->cache) {
             r->http_version = NGX_HTTP_VERSION_9;
             return NGX_OK;
         }
diff --git a/src/http/modules/ngx_http_range_filter_module.c b/src/http/modules/ngx_http_range_filter_module.c
--- a/src/http/modules/ngx_http_range_filter_module.c
+++ b/src/http/modules/ngx_http_range_filter_module.c
@@ -587,15 +587,8 @@ ngx_http_range_test_overlapped(ngx_http_
     buf = in->buf;
 
     if (!buf->last_buf) {
-
-        if (buf->in_file) {
-            start = buf->file_pos + ctx->offset;
-            last = buf->file_last + ctx->offset;
-
-        } else {
-            start = buf->pos - buf->start + ctx->offset;
-            last = buf->last - buf->start + ctx->offset;
-        }
+        start = ctx->offset;
+        last = ctx->offset + ngx_buf_size(buf);
 
         range = ctx->ranges.elts;
         for (i = 0; i < ctx->ranges.nelts; i++) {
@@ -708,7 +701,6 @@ static ngx_int_t
 ngx_http_range_multipart_body(ngx_http_request_t *r,
     ngx_http_range_filter_ctx_t *ctx, ngx_chain_t *in)
 {
-    off_t              body_start;
     ngx_buf_t         *b, *buf;
     ngx_uint_t         i;
     ngx_chain_t       *out, *hcl, *rcl, *dcl, **ll;
@@ -718,12 +710,6 @@ ngx_http_range_multipart_body(ngx_http_r
     buf = in->buf;
     range = ctx->ranges.elts;
 
-#if (NGX_HTTP_CACHE)
-    body_start = r->cached ? r->cache->body_start : 0;
-#else
-    body_start = 0;
-#endif
-
     for (i = 0; i < ctx->ranges.nelts; i++) {
 
         /*
@@ -784,13 +770,13 @@ ngx_http_range_multipart_body(ngx_http_r
         b->file = buf->file;
 
         if (buf->in_file) {
-            b->file_pos = body_start + range[i].start;
-            b->file_last = body_start + range[i].end;
+            b->file_pos = buf->file_pos + range[i].start;
+            b->file_last = buf->file_pos + range[i].end;
         }
 
         if (ngx_buf_in_memory(buf)) {
-            b->pos = buf->start + (size_t) range[i].start;
-            b->last = buf->start + (size_t) range[i].end;
+            b->pos = buf->pos + (size_t) range[i].start;
+            b->last = buf->pos + (size_t) range[i].end;
         }
 
         dcl = ngx_alloc_chain_link(r->pool);
diff --git a/src/http/modules/ngx_http_scgi_module.c b/src/http/modules/ngx_http_scgi_module.c
--- a/src/http/modules/ngx_http_scgi_module.c
+++ b/src/http/modules/ngx_http_scgi_module.c
@@ -494,7 +494,7 @@ ngx_http_scgi_create_key(ngx_http_reques
     ngx_str_t                 *key;
     ngx_http_scgi_loc_conf_t  *scf;
 
-    key = ngx_array_push(&r->cache->keys);
+    key = ngx_array_push(&r->upstream->cache->keys);
     if (key == NULL) {
         return NGX_ERROR;
     }
diff --git a/src/http/modules/ngx_http_uwsgi_module.c b/src/http/modules/ngx_http_uwsgi_module.c
--- a/src/http/modules/ngx_http_uwsgi_module.c
+++ b/src/http/modules/ngx_http_uwsgi_module.c
@@ -527,7 +527,7 @@ ngx_http_uwsgi_create_key(ngx_http_reque
     ngx_str_t                  *key;
     ngx_http_uwsgi_loc_conf_t  *uwcf;
 
-    key = ngx_array_push(&r->cache->keys);
+    key = ngx_array_push(&r->upstream->cache->keys);
     if (key == NULL) {
         return NGX_ERROR;
     }
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
@@ -124,13 +124,16 @@ struct ngx_http_file_cache_s {
 };
 
 
-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);
-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 *);
+ngx_http_cache_t *ngx_http_file_cache_new(ngx_http_request_t *r);
+ngx_int_t ngx_http_file_cache_create(ngx_http_request_t *r,
+    ngx_http_cache_t *c);
+void ngx_http_file_cache_create_key(ngx_http_request_t *r, ngx_http_cache_t *c);
+ngx_int_t ngx_http_file_cache_open(ngx_http_request_t *r, ngx_http_cache_t *c);
+void ngx_http_file_cache_set_header(ngx_http_request_t *r, ngx_http_cache_t *c,
+    u_char *buf);
+void ngx_http_file_cache_update(ngx_http_request_t *r, ngx_http_cache_t *c,
+    ngx_temp_file_t *tf);
+ngx_int_t ngx_http_cache_send(ngx_http_request_t *r, ngx_http_cache_t *c);
 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);
 
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
@@ -2339,10 +2339,6 @@ ngx_http_internal_redirect(ngx_http_requ
 
     ngx_http_update_location_config(r);
 
-#if (NGX_HTTP_CACHE)
-    r->cache = NULL;
-#endif
-
     r->internal = 1;
     r->add_uri_to_alias = 0;
     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
@@ -20,7 +20,7 @@ static void ngx_http_cache_aio_event_han
 static ngx_int_t ngx_http_file_cache_exists(ngx_http_file_cache_t *cache,
     ngx_http_cache_t *c);
 static ngx_int_t ngx_http_file_cache_name(ngx_http_request_t *r,
-    ngx_path_t *path);
+    ngx_http_cache_t *c, ngx_path_t *path);
 static ngx_http_file_cache_node_t *
     ngx_http_file_cache_lookup(ngx_http_file_cache_t *cache, u_char *key);
 static void ngx_http_file_cache_rbtree_insert_value(ngx_rbtree_node_t *temp,
@@ -145,38 +145,35 @@ ngx_http_file_cache_init(ngx_shm_zone_t 
 }
 
 
-ngx_int_t
+ngx_http_cache_t *
 ngx_http_file_cache_new(ngx_http_request_t *r)
 {
     ngx_http_cache_t  *c;
 
     c = ngx_pcalloc(r->pool, sizeof(ngx_http_cache_t));
     if (c == NULL) {
-        return NGX_ERROR;
+        return NULL;
     }
 
     if (ngx_array_init(&c->keys, r->pool, 4, sizeof(ngx_str_t)) != NGX_OK) {
-        return NGX_ERROR;
+        return NULL;
     }
 
-    r->cache = c;
     c->file.log = r->connection->log;
     c->file.fd = NGX_INVALID_FILE;
 
-    return NGX_OK;
+    return c;
 }
 
 
 ngx_int_t
-ngx_http_file_cache_create(ngx_http_request_t *r)
+ngx_http_file_cache_create(ngx_http_request_t *r, ngx_http_cache_t *c)
 {
-    ngx_http_cache_t       *c;
     ngx_pool_cleanup_t     *cln;
     ngx_http_file_cache_t  *cache;
 
-    ngx_http_file_cache_create_key(r);
+    ngx_http_file_cache_create_key(r, c);
 
-    c = r->cache;
     cache = c->file_cache;
 
     cln = ngx_pool_cleanup_add(r->pool, 0);
@@ -191,7 +188,7 @@ ngx_http_file_cache_create(ngx_http_requ
     cln->handler = ngx_http_file_cache_cleanup;
     cln->data = c;
 
-    if (ngx_http_file_cache_name(r, cache->path) != NGX_OK) {
+    if (ngx_http_file_cache_name(r, c, cache->path) != NGX_OK) {
         return NGX_ERROR;
     }
 
@@ -200,15 +197,12 @@ ngx_http_file_cache_create(ngx_http_requ
 
 
 void
-ngx_http_file_cache_create_key(ngx_http_request_t *r)
+ngx_http_file_cache_create_key(ngx_http_request_t *r, ngx_http_cache_t *c)
 {
     size_t             len;
     ngx_str_t         *key;
     ngx_uint_t         i;
     ngx_md5_t          md5;
-    ngx_http_cache_t  *c;
-
-    c = r->cache;
 
     len = 0;
 
@@ -235,18 +229,15 @@ ngx_http_file_cache_create_key(ngx_http_
 
 
 ngx_int_t
-ngx_http_file_cache_open(ngx_http_request_t *r)
+ngx_http_file_cache_open(ngx_http_request_t *r, ngx_http_cache_t *c)
 {
     ngx_int_t                  rc, rv;
     ngx_uint_t                 cold, test;
-    ngx_http_cache_t          *c;
     ngx_pool_cleanup_t        *cln;
     ngx_open_file_info_t       of;
     ngx_http_file_cache_t     *cache;
     ngx_http_core_loc_conf_t  *clcf;
 
-    c = r->cache;
-
     if (c->buf) {
         return ngx_http_file_cache_read(r, c);
     }
@@ -304,7 +295,7 @@ ngx_http_file_cache_open(ngx_http_reques
         }
     }
 
-    if (ngx_http_file_cache_name(r, cache->path) != NGX_OK) {
+    if (ngx_http_file_cache_name(r, c, cache->path) != NGX_OK) {
         return NGX_ERROR;
     }
 
@@ -397,8 +388,6 @@ ngx_http_file_cache_read(ngx_http_reques
     c->header_start = h->header_start;
     c->body_start = h->body_start;
 
-    r->cached = 1;
-
     cache = c->file_cache;
 
     if (cache->sh->cold) {
@@ -615,12 +604,10 @@ failed:
 
 
 static ngx_int_t
-ngx_http_file_cache_name(ngx_http_request_t *r, ngx_path_t *path)
+ngx_http_file_cache_name(ngx_http_request_t *r, ngx_http_cache_t *c,
+    ngx_path_t *path)
 {
     u_char            *p;
-    ngx_http_cache_t  *c;
-
-    c = r->cache;
 
     c->file.name.len = path->name.len + 1 + path->len
                        + 2 * NGX_HTTP_CACHE_KEY_LEN;
@@ -739,20 +726,18 @@ ngx_http_file_cache_rbtree_insert_value(
 
 
 void
-ngx_http_file_cache_set_header(ngx_http_request_t *r, u_char *buf)
+ngx_http_file_cache_set_header(ngx_http_request_t *r, ngx_http_cache_t *c,
+    u_char *buf)
 {
     ngx_http_file_cache_header_t  *h = (ngx_http_file_cache_header_t *) buf;
 
     u_char            *p;
     ngx_str_t         *key;
     ngx_uint_t         i;
-    ngx_http_cache_t  *c;
 
     ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
                    "http file cache set header");
 
-    c = r->cache;
-
     h->valid_sec = c->valid_sec;
     h->last_modified = c->last_modified;
     h->date = c->date;
@@ -775,18 +760,16 @@ ngx_http_file_cache_set_header(ngx_http_
 
 
 void
-ngx_http_file_cache_update(ngx_http_request_t *r, ngx_temp_file_t *tf)
+ngx_http_file_cache_update(ngx_http_request_t *r, ngx_http_cache_t *c,
+    ngx_temp_file_t *tf)
 {
     off_t                   size, length;
     ngx_int_t               rc;
     ngx_file_uniq_t         uniq;
     ngx_file_info_t         fi;
-    ngx_http_cache_t        *c;
     ngx_ext_rename_file_t   ext;
     ngx_http_file_cache_t  *cache;
 
-    c = r->cache;
-
     if (c->updated) {
         return;
     }
@@ -854,14 +837,11 @@ ngx_http_file_cache_update(ngx_http_requ
 
 
 ngx_int_t
-ngx_http_cache_send(ngx_http_request_t *r)
+ngx_http_cache_send(ngx_http_request_t *r, ngx_http_cache_t *c)
 {
     ngx_int_t          rc;
     ngx_buf_t         *b;
     ngx_chain_t        out;
-    ngx_http_cache_t  *c;
-
-    c = r->cache;
 
     ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
                   "http file cache send: %s", c->file.name.data);
diff --git a/src/http/ngx_http_request.h b/src/http/ngx_http_request.h
--- a/src/http/ngx_http_request.h
+++ b/src/http/ngx_http_request.h
@@ -354,10 +354,6 @@ struct ngx_http_request_s {
     ngx_http_event_handler_pt         read_event_handler;
     ngx_http_event_handler_pt         write_event_handler;
 
-#if (NGX_HTTP_CACHE)
-    ngx_http_cache_t                 *cache;
-#endif
-
     ngx_http_upstream_t              *upstream;
     ngx_array_t                      *upstream_states;
                                          /* of ngx_http_upstream_state_t */
@@ -460,10 +456,6 @@ struct ngx_http_request_s {
     unsigned                          subrequest_in_memory:1;
     unsigned                          waited:1;
 
-#if (NGX_HTTP_CACHE)
-    unsigned                          cached:1;
-#endif
-
 #if (NGX_HTTP_GZIP)
     unsigned                          gzip_tested:1;
     unsigned                          gzip_ok:1;
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
@@ -392,10 +392,6 @@ ngx_http_upstream_create(ngx_http_reques
     u->peer.lock = &r->connection->lock;
 #endif
 
-#if (NGX_HTTP_CACHE)
-    r->cache = NULL;
-#endif
-
     return NGX_OK;
 }
 
@@ -629,7 +625,7 @@ ngx_http_upstream_cache(ngx_http_request
     ngx_int_t          rc;
     ngx_http_cache_t  *c;
 
-    c = r->cache;
+    c = u->cache;
 
     if (c == NULL) {
 
@@ -654,22 +650,23 @@ ngx_http_upstream_cache(ngx_http_request
             u->method = ngx_http_core_get_method;
         }
 
-        if (ngx_http_file_cache_new(r) != NGX_OK) {
+        u->cache = ngx_http_file_cache_new(r);
+        if (u->cache == NULL) {
             return NGX_ERROR;
         }
 
+        c = u->cache;
+
         if (u->create_key(r) != NGX_OK) {
             return NGX_ERROR;
         }
 
         /* TODO: add keys */
 
-        ngx_http_file_cache_create_key(r);
+        ngx_http_file_cache_create_key(r, c);
 
         u->cacheable = 1;
 
-        c = r->cache;
-
         c->min_uses = u->conf->cache_min_uses;
         c->body_start = u->conf->buffer_size;
         c->file_cache = u->conf->cache->data;
@@ -677,7 +674,7 @@ ngx_http_upstream_cache(ngx_http_request
         u->cache_status = NGX_HTTP_CACHE_MISS;
     }
 
-    rc = ngx_http_file_cache_open(r);
+    rc = ngx_http_file_cache_open(r, c);
 
     ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
                    "http upstream cache: %i", rc);
@@ -755,7 +752,7 @@ ngx_http_upstream_cache(ngx_http_request
         return rc;
     }
 
-    r->cached = 0;
+    u->cached = 0;
 
     return NGX_DECLINED;
 }
@@ -767,12 +764,12 @@ ngx_http_upstream_cache_send(ngx_http_re
     ngx_int_t          rc;
     ngx_http_cache_t  *c;
 
-    r->cached = 1;
-    c = r->cache;
+    u->cached = 1;
+    c = u->cache;
 
     if (c->header_start == c->body_start) {
         r->http_version = NGX_HTTP_VERSION_9;
-        return ngx_http_cache_send(r);
+        return ngx_http_cache_send(r, c);
     }
 
     /* TODO: cache stack */
@@ -797,7 +794,7 @@ ngx_http_upstream_cache_send(ngx_http_re
             return NGX_DONE;
         }
 
-        return ngx_http_cache_send(r);
+        return ngx_http_cache_send(r, c);
     }
 
     if (rc == NGX_ERROR) {
@@ -1306,8 +1303,8 @@ ngx_http_upstream_reinit(ngx_http_reques
 
 #if (NGX_HTTP_CACHE)
 
-    if (r->cache) {
-        u->buffer.pos += r->cache->header_start;
+    if (u->cache) {
+        u->buffer.pos += u->cache->header_start;
     }
 
 #endif
@@ -1491,8 +1488,8 @@ ngx_http_upstream_process_header(ngx_htt
 
 #if (NGX_HTTP_CACHE)
 
-        if (r->cache) {
-            u->buffer.pos += r->cache->header_start;
+        if (u->cache) {
+            u->buffer.pos += u->cache->header_start;
             u->buffer.last = u->buffer.pos;
         }
 #endif
@@ -1722,17 +1719,17 @@ ngx_http_upstream_intercept_errors(ngx_h
 
 #if (NGX_HTTP_CACHE)
 
-            if (r->cache) {
+            if (u->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;
+                    u->cache->valid_sec = ngx_time() + valid;
+                    u->cache->error = status;
                 }
 
-                ngx_http_file_cache_free(r->cache, u->pipe->temp_file);
+                ngx_http_file_cache_free(u->cache, u->pipe->temp_file);
             }
 #endif
             ngx_http_upstream_finalize_request(r, u, status);
@@ -2108,9 +2105,9 @@ ngx_http_upstream_send_response(ngx_http
 
 #if (NGX_HTTP_CACHE)
 
-    if (r->cache && r->cache->file.fd != NGX_INVALID_FILE) {
-        ngx_pool_run_cleanup_file(r->pool, r->cache->file.fd);
-        r->cache->file.fd = NGX_INVALID_FILE;
+    if (u->cache && u->cache->file.fd != NGX_INVALID_FILE) {
+        ngx_pool_run_cleanup_file(r->pool, u->cache->file.fd);
+        u->cache->file.fd = NGX_INVALID_FILE;
     }
 
     switch (ngx_http_test_predicates(r, u->conf->no_cache)) {
@@ -2127,7 +2124,8 @@ ngx_http_upstream_send_response(ngx_http
 
         if (u->cache_status == NGX_HTTP_CACHE_BYPASS) {
 
-            if (ngx_http_file_cache_new(r) != NGX_OK) {
+            u->cache = ngx_http_file_cache_new(r);
+            if (u->cache == NULL) {
                 ngx_http_upstream_finalize_request(r, u, 0);
                 return;
             }
@@ -2139,11 +2137,11 @@ ngx_http_upstream_send_response(ngx_http
 
             /* TODO: add keys */
 
-            r->cache->min_uses = u->conf->cache_min_uses;
-            r->cache->body_start = u->conf->buffer_size;
-            r->cache->file_cache = u->conf->cache->data;
-
-            if (ngx_http_file_cache_create(r) != NGX_OK) {
+            u->cache->min_uses = u->conf->cache_min_uses;
+            u->cache->body_start = u->conf->buffer_size;
+            u->cache->file_cache = u->conf->cache->data;
+
+            if (ngx_http_file_cache_create(r, u->cache) != NGX_OK) {
                 ngx_http_upstream_finalize_request(r, u, 0);
                 return;
             }
@@ -2159,22 +2157,22 @@ ngx_http_upstream_send_response(ngx_http
 
         now = ngx_time();
 
-        valid = r->cache->valid_sec;
+        valid = u->cache->valid_sec;
 
         if (valid == 0) {
             valid = ngx_http_file_cache_valid(u->conf->cache_valid,
                                               u->headers_in.status_n);
             if (valid) {
-                r->cache->valid_sec = now + valid;
+                u->cache->valid_sec = now + valid;
             }
         }
 
         if (valid) {
-            r->cache->last_modified = r->headers_out.last_modified_time;
-            r->cache->date = now;
-            r->cache->body_start = (u_short) (u->buffer.pos - u->buffer.start);
-
-            ngx_http_file_cache_set_header(r, u->buffer.start);
+            u->cache->last_modified = r->headers_out.last_modified_time;
+            u->cache->date = now;
+            u->cache->body_start = (u_short) (u->buffer.pos - u->buffer.start);
+
+            ngx_http_file_cache_set_header(r, u->cache, u->buffer.start);
 
         } else {
             u->cacheable = 0;
@@ -2185,8 +2183,8 @@ ngx_http_upstream_send_response(ngx_http
     ngx_log_debug1(NGX_LOG_DEBUG_HTTP, c->log, 0,
                    "http cacheable: %d", u->cacheable);
 
-    if (u->cacheable == 0 && r->cache) {
-        ngx_http_file_cache_free(r->cache, u->pipe->temp_file);
+    if (u->cacheable == 0 && u->cache) {
+        ngx_http_file_cache_free(u->cache, u->pipe->temp_file);
     }
 
 #endif
@@ -2652,16 +2650,16 @@ ngx_http_upstream_process_request(ngx_ht
         if (u->cacheable) {
 
             if (p->upstream_done) {
-                ngx_http_file_cache_update(r, u->pipe->temp_file);
+                ngx_http_file_cache_update(r, u->cache, u->pipe->temp_file);
 
             } else if (p->upstream_eof) {
 
                 /* TODO: check length & update cache */
 
-                ngx_http_file_cache_update(r, u->pipe->temp_file);
+                ngx_http_file_cache_update(r, u->cache, u->pipe->temp_file);
 
             } else if (p->upstream_error) {
-                ngx_http_file_cache_free(r->cache, u->pipe->temp_file);
+                ngx_http_file_cache_free(u->cache, u->pipe->temp_file);
             }
         }
 
@@ -2986,7 +2984,7 @@ ngx_http_upstream_finalize_request(ngx_h
 
 #if (NGX_HTTP_CACHE)
 
-    if (u->cacheable && r->cache) {
+    if (u->cacheable) {
         time_t  valid;
 
         if (rc == NGX_HTTP_BAD_GATEWAY || rc == NGX_HTTP_GATEWAY_TIME_OUT) {
@@ -2994,12 +2992,12 @@ ngx_http_upstream_finalize_request(ngx_h
             valid = ngx_http_file_cache_valid(u->conf->cache_valid, rc);
 
             if (valid) {
-                r->cache->valid_sec = ngx_time() + valid;
-                r->cache->error = rc;
+                u->cache->valid_sec = ngx_time() + valid;
+                u->cache->error = rc;
             }
         }
 
-        ngx_http_file_cache_free(r->cache, u->pipe->temp_file);
+        ngx_http_file_cache_free(u->cache, u->pipe->temp_file);
     }
 
 #endif
@@ -3100,11 +3098,11 @@ ngx_http_upstream_process_cache_control(
         return NGX_OK;
     }
 
-    if (r->cache == NULL) {
+    if (u->cache == NULL) {
         return NGX_OK;
     }
 
-    if (r->cache->valid_sec != 0) {
+    if (u->cache->valid_sec != 0) {
         return NGX_OK;
     }
 
@@ -3146,7 +3144,7 @@ ngx_http_upstream_process_cache_control(
         return NGX_OK;
     }
 
-    r->cache->valid_sec = ngx_time() + n;
+    u->cache->valid_sec = ngx_time() + n;
     }
 #endif
 
@@ -3171,11 +3169,11 @@ ngx_http_upstream_process_expires(ngx_ht
         return NGX_OK;
     }
 
-    if (r->cache == NULL) {
+    if (u->cache == NULL) {
         return NGX_OK;
     }
 
-    if (r->cache->valid_sec != 0) {
+    if (u->cache->valid_sec != 0) {
         return NGX_OK;
     }
 
@@ -3186,7 +3184,7 @@ ngx_http_upstream_process_expires(ngx_ht
         return NGX_OK;
     }
 
-    r->cache->valid_sec = expires;
+    u->cache->valid_sec = expires;
     }
 #endif
 
@@ -3213,7 +3211,7 @@ ngx_http_upstream_process_accel_expires(
         return NGX_OK;
     }
 
-    if (r->cache == NULL) {
+    if (u->cache == NULL) {
         return NGX_OK;
     }
 
@@ -3230,7 +3228,7 @@ ngx_http_upstream_process_accel_expires(
             return NGX_OK;
 
         default:
-            r->cache->valid_sec = ngx_time() + n;
+            u->cache->valid_sec = ngx_time() + n;
             return NGX_OK;
         }
     }
@@ -3241,7 +3239,7 @@ ngx_http_upstream_process_accel_expires(
     n = ngx_atoi(p, len);
 
     if (n != NGX_ERROR) {
-        r->cache->valid_sec = n;
+        u->cache->valid_sec = n;
     }
     }
 #endif
@@ -3562,10 +3560,9 @@ ngx_http_upstream_copy_allow_ranges(ngx_
 
 #if (NGX_HTTP_CACHE)
 
-    if (r->cached) {
+    if (r->upstream->cached) {
         r->allow_ranges = 1;
         return NGX_OK;
-
     }
 
 #endif
diff --git a/src/http/ngx_http_upstream.h b/src/http/ngx_http_upstream.h
--- a/src/http/ngx_http_upstream.h
+++ b/src/http/ngx_http_upstream.h
@@ -265,6 +265,10 @@ struct ngx_http_upstream_s {
 
     ngx_http_upstream_resolved_t    *resolved;
 
+#if (NGX_HTTP_CACHE)
+    ngx_http_cache_t                *cache;
+#endif
+
     ngx_buf_t                        buffer;
     size_t                           length;
 
@@ -303,6 +307,7 @@ struct ngx_http_upstream_s {
     unsigned                         accel:1;
     unsigned                         ssl:1;
 #if (NGX_HTTP_CACHE)
+    unsigned                         cached:1;
     unsigned                         cache_status:3;
 #endif
 


More information about the nginx mailing list