Commit c4dd756f authored by Paul Querna's avatar Paul Querna
Browse files

- Use apr_file_mktemp() and rename the header data file to its final location,...

- 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
parent 5b2ee0a9
Loading
Loading
Loading
Loading
+2 −0
Changes for CHANGES: 2 added lines, 0 removed lines.
Original line number Diff line number Diff line
@@ -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]
+24 −11
Changes for modules/cache/mod_disk_cache.c: 24 added lines, 11 removed lines.
Original line number Diff line number Diff line
@@ -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;