Mercurial > hg > nginx
comparison src/http/ngx_http_file_cache.c @ 4436:311b358658c8 stable-1.0
Merge of r4339, r4340, r4341:
Cache fixes:
*) Obsolete code removed.
The ngx_http_cache() and ngx_http_no_cache_set_slot() functions
were replaced in 0.8.46 and no longer used since then.
*) Handling of cache files with long headers.
There are two possible situations which can lead to this: response
was cached with bigger proxy_buffer_size value (and nginx was
restared since then, i.e. shared memory zone content was lost), or
due to the race in the cache update code (see [1]) we've end up
with fcn->body_start from a different response stored in shared
memory zone.
*) Only complain on long locked entries.
There have been multiple reports of cases where a real locked entry
was removed, resulting in a segmentation fault later in a worker
which locked the entry. It looks like default inactive timeout isn't
enough in real life.
For now just ignore such locked entries, and move them to the top of
the inactive queue to allow processing of other entries.
[1] http://mailman.nginx.org/pipermail/nginx-devel/2011-September/001287.html
author | Maxim Dounin <mdounin@mdounin.ru> |
---|---|
date | Sun, 05 Feb 2012 13:34:08 +0000 |
parents | 2fad4d19ea4b |
children | 4919fb357a5d |
comparison
equal
deleted
inserted
replaced
4435:3b9be99122b6 | 4436:311b358658c8 |
---|---|
385 ngx_log_error(NGX_LOG_CRIT, r->connection->log, 0, | 385 ngx_log_error(NGX_LOG_CRIT, r->connection->log, 0, |
386 "cache file \"%s\" has md5 collision", c->file.name.data); | 386 "cache file \"%s\" has md5 collision", c->file.name.data); |
387 return NGX_DECLINED; | 387 return NGX_DECLINED; |
388 } | 388 } |
389 | 389 |
390 if (h->body_start > c->body_start) { | |
391 ngx_log_error(NGX_LOG_CRIT, r->connection->log, 0, | |
392 "cache file \"%s\" has too long header", | |
393 c->file.name.data); | |
394 return NGX_DECLINED; | |
395 } | |
396 | |
390 c->buf->last += n; | 397 c->buf->last += n; |
391 | 398 |
392 c->valid_sec = h->valid_sec; | 399 c->valid_sec = h->valid_sec; |
393 c->last_modified = h->last_modified; | 400 c->last_modified = h->last_modified; |
394 c->date = h->date; | 401 c->date = h->date; |
1105 (void) ngx_hex_dump(p, fcn->key, len); | 1112 (void) ngx_hex_dump(p, fcn->key, len); |
1106 | 1113 |
1107 /* | 1114 /* |
1108 * abnormally exited workers may leave locked cache entries, | 1115 * abnormally exited workers may leave locked cache entries, |
1109 * and although it may be safe to remove them completely, | 1116 * and although it may be safe to remove them completely, |
1110 * we prefer to remove them from inactive queue and rbtree | 1117 * we prefer to just move them to the top of the inactive queue |
1111 * only, and to allow other leaks | |
1112 */ | 1118 */ |
1113 | 1119 |
1114 ngx_queue_remove(q); | 1120 ngx_queue_remove(q); |
1115 ngx_rbtree_delete(&cache->sh->rbtree, &fcn->node); | 1121 fcn->expire = ngx_time() + cache->inactive; |
1122 ngx_queue_insert_head(&cache->sh->queue, &fcn->queue); | |
1116 | 1123 |
1117 ngx_log_error(NGX_LOG_ALERT, ngx_cycle->log, 0, | 1124 ngx_log_error(NGX_LOG_ALERT, ngx_cycle->log, 0, |
1118 "ignore long locked inactive cache entry %*s, count:%d", | 1125 "ignore long locked inactive cache entry %*s, count:%d", |
1119 2 * NGX_HTTP_CACHE_KEY_LEN, key, fcn->count); | 1126 2 * NGX_HTTP_CACHE_KEY_LEN, key, fcn->count); |
1120 } | 1127 } |
1708 v->valid = valid; | 1715 v->valid = valid; |
1709 } | 1716 } |
1710 | 1717 |
1711 return NGX_CONF_OK; | 1718 return NGX_CONF_OK; |
1712 } | 1719 } |
1713 | |
1714 | |
1715 ngx_int_t | |
1716 ngx_http_cache(ngx_http_request_t *r, ngx_array_t *no_cache) | |
1717 { | |
1718 ngx_str_t val; | |
1719 ngx_uint_t i; | |
1720 ngx_http_complex_value_t *cv; | |
1721 | |
1722 cv = no_cache->elts; | |
1723 | |
1724 for (i = 0; i < no_cache->nelts; i++) { | |
1725 if (ngx_http_complex_value(r, &cv[i], &val) != NGX_OK) { | |
1726 return NGX_ERROR; | |
1727 } | |
1728 | |
1729 if (val.len && val.data[0] != '0') { | |
1730 return NGX_DECLINED; | |
1731 } | |
1732 } | |
1733 | |
1734 return NGX_OK; | |
1735 } | |
1736 | |
1737 | |
1738 char * | |
1739 ngx_http_no_cache_set_slot(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) | |
1740 { | |
1741 char *p = conf; | |
1742 | |
1743 ngx_str_t *value; | |
1744 ngx_uint_t i; | |
1745 ngx_array_t **a; | |
1746 ngx_http_complex_value_t *cv; | |
1747 ngx_http_compile_complex_value_t ccv; | |
1748 | |
1749 a = (ngx_array_t **) (p + cmd->offset); | |
1750 | |
1751 if (*a == NGX_CONF_UNSET_PTR) { | |
1752 *a = ngx_array_create(cf->pool, 1, sizeof(ngx_http_complex_value_t)); | |
1753 if (*a == NULL) { | |
1754 return NGX_CONF_ERROR; | |
1755 } | |
1756 } | |
1757 | |
1758 value = cf->args->elts; | |
1759 | |
1760 for (i = 1; i < cf->args->nelts; i++) { | |
1761 cv = ngx_array_push(*a); | |
1762 if (cv == NULL) { | |
1763 return NGX_CONF_ERROR; | |
1764 } | |
1765 | |
1766 ngx_memzero(&ccv, sizeof(ngx_http_compile_complex_value_t)); | |
1767 | |
1768 ccv.cf = cf; | |
1769 ccv.value = &value[i]; | |
1770 ccv.complex_value = cv; | |
1771 | |
1772 if (ngx_http_compile_complex_value(&ccv) != NGX_OK) { | |
1773 return NGX_CONF_ERROR; | |
1774 } | |
1775 } | |
1776 | |
1777 return NGX_CONF_OK; | |
1778 } |