httpd-40064

Version:

2.2.6 (fixed in 2.2.7)

Bug link:

https://issues.apache.org/bugzilla/show_bug.cgi?id=40064

Symptom (Failure):
The ETag, a unique identifier for each url for cache validation purpose, for the same file is computed differently on 32-bit and 64-bit machines. This would cause performance problem in a large server farm. Wrong result!

How it is diagnosed:

Source analysis (we didn’t reproduce the failure).

Root Cause:

When computing ETag, Apache needs to use the field: r->mtime, which is declared as type: apr_int64_t (64 bit integer). However, when computing etag, it is casted to (unsigned long), which is 32 bits on 32bit machines. So the fix is to use the correct casting.

typedef apr_int64_t apr_time_t;

struct request_rec {

   …. ….

   /** Last modified time of the requested resource */

   apr_time_t mtime;

}

AP_DECLARE(char *) ap_make_etag(request_rec *r, int force_weak)

{

      … …

-      next = etag_ulong_to_hex(next, (unsigned long)r->mtime);

+      next = etag_ulong_to_hex(next, (apr_int64_t)r->mtime);

 

}

Is there any log message?:

No.

Can Errlog automatically insert an error msg?

No.

Discussions:

The error condition (ETag not match) is already checked by the developers. Therefore the developers could have been more conservative in logging this error. When the each request comes in, Apache is to check whether it is a cache hit by comparing the ETag provided from the HTTP header of the request (input check). When it notice ETag does not match, it can put a log message:

/* ap_meets_conditions checks if the input request can be served by cache or not. */

ap_meets_conditions () {

   /* Find etag from the input request header. */

   etag = apr_table_get(r->headers_out, "ETag");

   … …

   /* Check if the ETag matches. */

   not_modified = ap_find_list_item(r->pool,

                                                    if_nonematch, etag);

   // Here, developers can log when the input (ETag) does not match any cached ETag.

   

}