aboutsummaryrefslogtreecommitdiff
path: root/src/http/ngx_http_file_cache.c
Commit message (Collapse)AuthorAge
* Fixed request termination with AIO and subrequests (ticket #2555).Maxim Dounin2024-01-30
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | When a request was terminated due to an error via ngx_http_terminate_request() while an AIO operation was running in a subrequest, various issues were observed. This happened because ngx_http_request_finalizer() was only set in the subrequest where ngx_http_terminate_request() was called, but not in the subrequest where the AIO operation was running. After completion of the AIO operation normal processing of the subrequest was resumed, leading to issues. In particular, in case of the upstream module, termination of the request called upstream cleanup, which closed the upstream connection. Attempts to further work with the upstream connection after AIO operation completion resulted in segfaults in ngx_ssl_recv(), "readv() failed (9: Bad file descriptor) while reading upstream" errors, or socket leaks. In ticket #2555, issues were observed with the following configuration with cache background update (with thread writing instrumented to introduce a delay, when a client closes the connection during an update): location = /background-and-aio-write { proxy_pass ... proxy_cache one; proxy_cache_valid 200 1s; proxy_cache_background_update on; proxy_cache_use_stale updating; aio threads; aio_write on; limit_rate 1000; } Similarly, the same issue can be seen with SSI, and can be caused by errors in subrequests, such as in the following configuration (where "/proxy" uses AIO, and "/sleep" returns 444 after some delay, causing request termination): location = /ssi-active-boom { ssi on; ssi_types *; return 200 ' <!--#include virtual="/proxy" --> <!--#include virtual="/sleep" --> '; limit_rate 1000; } Or the same with both AIO operation and the error in non-active subrequests (which needs slightly different handling, see below): location = /ssi-non-active-boom { ssi on; ssi_types *; return 200 ' <!--#include virtual="/static" --> <!--#include virtual="/proxy" --> <!--#include virtual="/sleep" --> '; limit_rate 1000; } Similarly, issues can be observed with just static files. However, with static files potential impact is limited due to timeout safeguards in ngx_http_writer(), and the fact that c->error is set during request termination. In a simple configuration with an AIO operation in the active subrequest, such as in the following configuration, the connection is closed right after completion of the AIO operation anyway, since ngx_http_writer() tries to write to the connection and fails due to c->error set: location = /ssi-active-static-boom { ssi on; ssi_types *; return 200 ' <!--#include virtual="/static-aio" --> <!--#include virtual="/sleep" --> '; limit_rate 1000; } In the following configuration, with an AIO operation in a non-active subrequest, the connection is closed only after send_timeout expires: location = /ssi-non-active-static-boom { ssi on; ssi_types *; return 200 ' <!--#include virtual="/static" --> <!--#include virtual="/static-aio" --> <!--#include virtual="/sleep" --> '; limit_rate 1000; } Fix is to introduce r->main->terminated flag, which is to be checked by AIO event handlers when the r->main->blocked counter is decremented. When the flag is set, handlers are expected to wake up the connection instead of the subrequest (which might be already cleaned up). Additionally, now ngx_http_request_finalizer() is always set in the active subrequest, so waking up the connection properly finalizes the request even if termination happened in a non-active subrequest.
* AIO operations now add timers (ticket #2162).Maxim Dounin2024-01-29
| | | | | | | | | | | | Each AIO (thread IO) operation being run is now accompanied with 1-minute timer. This timer prevents unexpected shutdown of the worker process while an AIO operation is running, and logs an alert if the operation is running for too long. This fixes "open socket left" alerts during worker processes shutdown due to pending AIO (or thread IO) operations while corresponding requests have no timers. In particular, such errors were observed while reading cache headers (ticket #2162), and with worker_shutdown_timeout.
* Fixed "zero size buf" alerts with subrequests.Maxim Dounin2023-01-28
| | | | | | | | | | | | | | | | | Since 4611:2b6cb7528409 responses from the gzip static, flv, and mp4 modules can be used with subrequests, though empty files were not properly handled. Empty gzipped, flv, and mp4 files thus resulted in "zero size buf in output" alerts. While valid corresponding files are not expected to be empty, such files shouldn't result in alerts. Fix is to set b->sync on such empty subrequest responses, similarly to what ngx_http_send_special() does. Additionally, the static module, the ngx_http_send_response() function, and file cache are modified to do the same instead of not sending the response body at all in such cases, since not sending the response body at all is believed to be at least questionable, and might break various filters which do not expect such behaviour.
* Style.Maxim Dounin2023-01-28
|
* Cache: fixed race in ngx_http_file_cache_forced_expire().Maxim Dounin2022-02-01
| | | | | | | | | | | | | During configuration reload two cache managers might exist for a short time. If both tried to delete the same cache node, the "ignore long locked inactive cache entry" alert appeared in logs. Additionally, ngx_http_file_cache_forced_expire() might be also called by worker processes, with similar results. Fix is to ignore cache nodes being deleted, similarly to how it is done in ngx_http_file_cache_expire() since 3755:76e3a93821b1. This was somehow missed in 7002:ab199f0eb8e8, when ignoring long locked cache entries was introduced in ngx_http_file_cache_forced_expire().
* Cache: keep c->body_start when Vary changes (ticket #2029).Sergey Kandaurov2020-09-09
| | | | | | | | If the variant hash doesn't match one we used as a secondary cache key, we switch back to the original key. In this case, c->body_start was kept updated from an existing cache node overwriting the new response value. After file cache update, it led to discrepancy between a cache node and cache file seen as critical errors "file cache .. has too long header".
* Cache: reset c->body_start when reading a variant on Vary mismatch.Sergey Kandaurov2017-08-04
| | | | | | Previously, a variant not present in shared memory and stored on disk using a secondary key was read using c->body_start from a variant stored with a main key. This could result in critical errors "cache file .. has too long header".
* Cache: introduced min_free cache clearing.Maxim Dounin2020-06-22
| | | | | | | | | | | Clearing cache based on free space left on a file system is expected to allow better disk utilization in some cases, notably when disk space might be also used for something other than nginx cache (including nginx own temporary files) and while loading cache (when cache size might be inaccurate for a while, effectively disabling max_size cache clearing). Based on a patch by Adam Bambuch.
* Cache: improved keys zone size error reporting.Maxim Dounin2018-10-31
| | | | | After this change, too small keys zones are explicitly reported as such, much like in the other modules which use shared memory.
* Cache: fixed minimum cache keys zone size limit.Maxim Dounin2018-10-31
| | | | | | | | | | | | | | | | | Size of a shared memory zones must be at least two pages - one page for slab allocator internal data, and another page for actual allocations. Using 8192 instead is wrong, as there are systems with page sizes other than 4096. Note well that two pages is usually too low as well. In particular, cache is likely to use two allocations of different sizes for global structures, and at least four pages will be needed to properly allocate cache nodes. Except in a few very special cases, with keys zone of just two pages nginx won't be able to start. Other uses of shared memory impose a limit of 8 pages, which provides some room for global allocations. This patch doesn't try to address this though. Inspired by ticket #1665.
* Cache: status must be less then 599 in *_cache_valid directives.Gena Makhomed2018-09-24
| | | | | | | | | Previously, configurations with typo, for example fastcgi_cache_valid 200301 302 5m; successfully pass configuration test. Adding check for status codes > 599, and such configurations are now properly rejected.
* Cache: fixed cache valid slot to reject incorrect statuses.Maxim Dounin2018-04-18
| | | | | | | | | Previously, result of ngx_atoi() was assigned to an ngx_uint_t variable, and errors reported by ngx_atoi() became positive, so the following check in "status < 100" failed to catch them. This resulted in the configurations like "proxy_cache_valid 2xx 30s" being accepted as correct, while they in fact do nothing. Changing type to ngx_int_t fixes this, and such configurations are now properly rejected.
* Cache: fixed max_size on win32.Ruslan Ermilov2017-07-26
|
* Cache: ignore long locked entries during forced expire.Dmitry Volyntsev2017-05-18
| | | | | | | | | | Abnormally exited workers may leave locked cache entries, this can result in the cache size on disk exceeding max_size and shared memory exhaustion. This change mitigates the issue by ignoring locked entries during forced expire. It also increases the visibility of the problem by logging such entries.
* Use ngx_calloc_buf() where appropriate.Ruslan Ermilov2017-04-12
|
* Upstream: proxy_cache_background_update and friends.Roman Arutyunyan2017-02-10
| | | | The directives enable cache updates in subrequests.
* Cache: support for stale-while-revalidate and stale-if-error.Roman Arutyunyan2016-12-22
| | | | | | | | Previously, there was no way to enable the proxy_cache_use_stale behavior by reading the backend response. Now, stale-while-revalidate and stale-if-error Cache-Control extensions (RFC 5861) are supported. They specify, how long a stale response can be used when a cache entry is being updated, or in case of an error.
* Win32: fixed some warnings reported by Borland C.Maxim Dounin2016-12-24
| | | | | | | | | Most notably, warning W8012 (comparing signed and unsigned values) reported in multiple places where an unsigned value of small type (e.g., u_short) is promoted to an int and compared to an unsigned value. Warning W8072 (suspicious pointer arithmetic) disabled, it is reported when we increment base pointer in ngx_shm_alloc().
* Cache: prefix-based temporary files.Maxim Dounin2016-11-03
| | | | | | | | | | | On Linux, the rename syscall can be slow due to a global file system lock, acquired for the entire rename operation, unless both old and new files are in the same directory. To address this temporary files are now created in the same directory as the expected resulting cache file when using the "use_temp_path=off" parameter. This change mostly reverts 99639bfdfa2a and 3281de8142f5, restoring the behaviour as of a9138c35120d (with minor changes).
* Cache: cache manager debugging.Ruslan Ermilov2016-10-13
|
* Cache: cache manager limits.Dmitry Volyntsev2016-10-05
| | | | | | | | | The new parameters "manager_files", "manager_sleep" and "manager_threshold" were added to proxy_cache_path and friends. Note that ngx_path_manager_pt was changed to return ngx_msec_t instead of time_t (API change).
* Use NGX_MAX_PATH_LEVEL where appropriate.Ruslan Ermilov2016-07-06
| | | | The macro was unused since 0.7.44.
* Cache: fixed updating bypassed cached errors (ticket #827).Maxim Dounin2016-05-16
|
* Fixed logging with variable field width.Sergey Kandaurov2016-03-31
|
* Cache: fixed slots accounting error introduced in c9d680b00744.Dmitry Volyntsev2016-03-23
|
* Cache: added watermark to reduce IO load when keys_zone is full.Dmitry Volyntsev2016-03-18
| | | | | | | | When a keys_zone is full then each next request to the cache is penalized. That is, the cache has to evict older files to get a slot from the keys_zone synchronously. The patch introduces new behavior in this scenario. Manager will try to maintain available free slots in the keys_zone by cleaning old files in the background.
* Cache: report error if slab allocator fails during cache loading.Dmitry Volyntsev2016-03-18
|
* Threads: task pointer stored in ngx_file_t.Maxim Dounin2016-03-18
| | | | | | | | | | | | | | This simplifies the interface of the ngx_thread_read() function. Additionally, most of the thread operations now explicitly set file->thread_task, file->thread_handler and file->thread_ctx, to facilitate use of thread operations in other places. (Potential problems remain with sendfile in threads though - it uses file->thread_handler as set in ngx_output_chain(), and it should not be overwritten to an incompatible one.) In collaboration with Valentin Bartenev.
* Cache: check the whole cache key in addition to hashes.Maxim Dounin2015-09-11
| | | | | | | | | | This prevents a potential attack that discloses cached data if an attacker will be able to craft a hash collision between some cache key the attacker is allowed to access and another cache key with protected data. See http://mailman.nginx.org/pipermail/nginx-devel/2015-September/007288.html. Thanks to Gena Makhomed and Sergey Brester.
* Cache: added support for reading of the header in thread pools.Valentin Bartenev2015-04-01
|
* Added support for offloading read() in thread pools.Valentin Bartenev2015-03-14
|
* Cache: do not inherit last_modified and etag from stale response.Roman Arutyunyan2015-03-02
| | | | | | | | | | | | | | | | When replacing a stale cache entry, its last_modified and etag could be inherited from the old entry if the response code is not 200 or 206. Moreover, etag could be inherited with any response code if it's missing in the new response. As a result, the cache entry is left with invalid last_modified or etag which could lead to broken revalidation. For example, when a file is deleted from backend, its last_modified is copied to the new 404 cache entry and is used later for revalidation. Once the old file appears again with its original timestamp, revalidation succeeds and the cached 404 response is sent to client instead of the file. The problem appeared with etags in 44b9ab7752e3 (1.7.3) and affected last_modified in 1573fc7875fa (1.7.9).
* Cache: reduced diffs to the plus version of nginx.Ruslan Ermilov2015-02-17
| | | | No functional changes.
* Cache: added temp_path to file cache.Roman Arutyunyan2015-02-02
| | | | | | If use_temp_path is set to off, a subdirectory "temp" is created in the cache directory. It's used instead of proxy_temp_path and friends for caching upstream response.
* Upstream: use_temp_path parameter of proxy_cache_path and friends.Valentin Bartenev2014-12-26
| | | | | When set to "off", temporary files for cacheable responses will be stored inside cache directory.
* Cache: update variant while setting header.Valentin Bartenev2014-12-26
| | | | | | Some parts of code related to handling variants of a resource moved into a separate function that is called earlier. This allows to use cache file name as a prefix for temporary file in the following patch.
* Upstream: added variables support to proxy_cache and friends.Valentin Bartenev2014-12-22
|
* Cache: send conditional requests only for cached 200/206 responses.Piotr Sikora2014-11-26
| | | | | | | | | | | | | | | | | | | RFC7232 says: The 304 (Not Modified) status code indicates that a conditional GET or HEAD request has been received and would have resulted in a 200 (OK) response if it were not for the fact that the condition evaluated to false. which means that there is no reason to send requests with "If-None-Match" and/or "If-Modified-Since" headers for responses cached with other status codes. Also, sending conditional requests for responses cached with other status codes could result in a strange behavior, e.g. upstream server returning 304 Not Modified for cached 404 Not Found responses, etc. Signed-off-by: Piotr Sikora <piotr@cloudflare.com>
* Cache: proper wakeup of subrequests.Maxim Dounin2014-12-02
| | | | | | | | | | | | | In case of a cache lock timeout and in the aio handler we now call r->write_event_handler() instead of a connection write handler, to make sure to run appropriate subrequest. Previous code failed to run inactive subrequests and hence resulted in suboptimal behaviour, see report by Yichun Zhang: http://mailman.nginx.org/pipermail/nginx-devel/2013-October/004435.html (Infinite hang claimed in the report seems impossible without 3rd party modules, as subrequests will be eventually woken up by the postpone filter.)
* Upstream: improved subrequest logging.Maxim Dounin2014-12-02
| | | | | | | To ensure proper logging make sure to set current_request in all event handlers, including resolve, ssl handshake, cache lock wait timer and aio read handlers. A macro ngx_http_set_log_request() introduced to simplify this.
* Cache: proxy_cache_lock_age and friends.Roman Arutyunyan2014-11-18
| | | | | | Once this age is reached, the cache lock is discarded and another request can acquire the lock. Requests which failed to acquire the lock are not allowed to cache the response.
* Cache: removed dead store in ngx_http_file_cache_vary_header().Maxim Dounin2014-11-05
| | | | Found by Clang Static Analyzer.
* Cache: normalization of some Vary headers.Maxim Dounin2014-10-27
| | | | | | Spaces in Accept-Charset, Accept-Encoding, and Accept-Language headers are now ignored. As per syntax of these headers spaces can only appear in places where they are optional.
* Cache: multiple variants of a resource now can be stored.Maxim Dounin2014-10-27
| | | | | | | | | If a variant stored can't be used to respond to a request, the variant hash is used as a secondary key. Additionally, if we previously switched to a secondary key, while storing a response to cache we check if the variant hash still apply. If not, we switch back to the original key, to handle cases when Vary changes.
* Cache: c->reading flag introduced.Maxim Dounin2014-10-27
| | | | | It replaces c->buf in checks in ngx_http_file_cache_open(), making it possible to reopen the file without clearing c->buf. No functional changes.
* Cache: hash of Vary headers now stored in cache.Maxim Dounin2014-10-27
| | | | | | | | To cache responses with Vary, we now calculate hash of headers listed in Vary, and return the response from cache only if new request headers match. As of now, only one variant of the same resource can be stored in cache.
* Upstream: suppressed the file cache slab allocator error messages.Roman Arutyunyan2014-09-05
| | | | | | | The messages "ngx_slab_alloc() failed: no memory in cache keys zone" from the file cache slab allocator are suppressed since the allocation is likely to succeed after the forced expiration of cache nodes. The second allocation failure is reported.
* Cache: ETag now saved into cache header.Maxim Dounin2014-06-26
|
* Cache: version in cache files.Maxim Dounin2014-06-26
| | | | | This allows to change the structure of cache files without spamming logs with false alerts.
* Core: added ngx_slab_calloc() and ngx_slab_calloc_locked().Ruslan Ermilov2014-06-04
| | | | These functions return zeroed memory, analogous to ngx_pcalloc().