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 }