Commit 4f5db0a5 authored by Justin Erenkrantz's avatar Justin Erenkrantz
Browse files

mod_disk_cache: Retry file rename up to three times to ameliorate race

condition with htcacheclean removing the directories underneath us.

(Includes tweaks by Justin.)

Suggested by: Graham Leggett
Submitted by: Andreas Steinmetz <ast@domdv.de>
Reviewed by: Justin Erenkrantz


git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@231349 13f79535-47bb-0310-9956-ffa450edef68
parent ef5d974d
Loading
Loading
Loading
Loading
+30 −3
Changes for modules/cache/mod_disk_cache.c: 30 added lines, 3 removed lines.
Original line number Diff line number Diff line
@@ -184,6 +184,33 @@ static void mkdir_structure(disk_cache_conf *conf, const char *file, apr_pool_t
    }
}

/* htcacheclean may remove directories underneath us.
 * So, we'll try renaming three times at a cost of 0.002 seconds.
 */
static apr_status_t safe_file_rename(disk_cache_conf *conf,
                                     const char *src, const char *dest,
                                     apr_pool_t *pool)
{
    apr_status_t rv;

    rv = apr_file_rename(src, dest, pool);

    if (rv != APR_SUCCESS) {
        int i;

        for (i = 0; i < 2 && rv != APR_SUCCESS; i++) {
            /* 1000 micro-seconds aka 0.001 seconds. */
            apr_sleep(1000);

            mkdir_structure(conf, dest, pool);

            rv = apr_file_rename(src, dest, pool);
        }
    }

    return rv;
}

static apr_status_t file_cache_el_final(disk_cache_object_t *dobj,
                                        request_rec *r)
{
@@ -795,7 +822,8 @@ static apr_status_t store_headers(cache_handle_t *h, request_rec *r, cache_info

            dobj->tfd = NULL;

            rv = apr_file_rename(dobj->tempfile, dobj->hdrsfile, r->pool);
            rv = safe_file_rename(conf, dobj->tempfile, dobj->hdrsfile,
                                  r->pool);
            if (rv != APR_SUCCESS) {
                ap_log_error(APLOG_MARK, APLOG_DEBUG, rv, r->server,
                    "disk_cache: rename tempfile to varyfile failed: %s -> %s",
@@ -887,8 +915,7 @@ static apr_status_t store_headers(cache_handle_t *h, request_rec *r, cache_info
        mkdir_structure(conf, dobj->hdrsfile, r->pool);
    }

    rv = apr_file_rename(dobj->tempfile, dobj->hdrsfile, r->pool);

    rv = safe_file_rename(conf, 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",