From 0d46d695a2b89de948f918be495b977185b10854 Mon Sep 17 00:00:00 2001 From: Paul Querna Date: Sat, 11 Jun 2005 00:26:19 +0000 Subject: [PATCH] - Use apr_file_mktemp() and rename the header data file to its final location, instead of opening it and then writing it out as we go. Should prevent race conditions on busy servers. git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@190043 13f79535-47bb-0310-9956-ffa450edef68 --- CHANGES | 2 ++ modules/cache/mod_disk_cache.c | 35 +++++++++++++++++++++++----------- 2 files changed, 26 insertions(+), 11 deletions(-) diff --git a/CHANGES b/CHANGES index 5201d1a35d..2fc99443af 100644 --- a/CHANGES +++ b/CHANGES @@ -2,6 +2,8 @@ Changes with Apache 2.1.5 [Remove entries to the current 2.0 section below, when backported] + *) mod_disk_cache: Atomically create the header data file. [Paul Querna] + *) mod_cache: Fix 'Vary: *' behavior to be RFC compliant. PR 16125. [Paul Querna] diff --git a/modules/cache/mod_disk_cache.c b/modules/cache/mod_disk_cache.c index b7365c4742..5e46c870ee 100644 --- a/modules/cache/mod_disk_cache.c +++ b/modules/cache/mod_disk_cache.c @@ -535,21 +535,14 @@ static apr_status_t store_headers(cache_handle_t *h, request_rec *r, cache_info /* This is flaky... we need to manage the cache_info differently */ h->cache_obj->info = *info; - /* Remove old file with the same name. If remove fails, then - * perhaps we need to create the directory tree where we are - * about to write the new headers file. - */ - rv = apr_file_remove(dobj->hdrsfile, r->pool); - if (rv != APR_SUCCESS) { - mkdir_structure(conf, dobj->hdrsfile, r->pool); - } + rv = apr_file_mktemp(&dobj->hfd, dobj->tempfile, + APR_CREATE | APR_WRITE | APR_BINARY | + APR_BUFFERED | APR_EXCL, r->pool); - rv = apr_file_open(&dobj->hfd, dobj->hdrsfile, - APR_WRITE | APR_CREATE | APR_EXCL, - APR_OS_DEFAULT, r->pool); if (rv != APR_SUCCESS) { return rv; } + dobj->name = h->cache_obj->key; disk_info.format = DISK_FORMAT_VERSION; @@ -607,6 +600,26 @@ static apr_status_t store_headers(cache_handle_t *h, request_rec *r, cache_info apr_file_close(dobj->hfd); /* flush and close */ + /* Remove old file with the same name. If remove fails, then + * perhaps we need to create the directory tree where we are + * about to write the new headers file. + */ + rv = apr_file_remove(dobj->hdrsfile, r->pool); + if (rv != APR_SUCCESS) { + mkdir_structure(conf, dobj->hdrsfile, r->pool); + } + + rv = apr_file_rename(dobj->tempfile, dobj->hdrsfile, r->pool); + + if (rv != APR_SUCCESS) { + ap_log_error(APLOG_MARK, APLOG_ERR, rv, r->server, + "disk_cache: rename tempfile to hdrsfile failed: %s -> %s", + dobj->tempfile, dobj->hdrsfile); + return rv; + } + + dobj->tempfile = apr_pstrcat(r->pool, conf->cache_root, AP_TEMPFILE, NULL); + ap_log_error(APLOG_MARK, APLOG_DEBUG, 0, r->server, "disk_cache: Stored headers for URL %s", dobj->name); return APR_SUCCESS; -- 2.40.0