[prev in list] [next in list] [prev in thread] [next in thread] 

List:       apache-httpd-bugs
Subject:    DO NOT REPLY [Bug 45868] New: mod_mem_cache update of headers in
From:       bugzilla () apache ! org
Date:       2008-09-23 23:46:33
Message-ID: bug-45868-7868 () https ! issues ! apache ! org/bugzilla/
[Download RAW message or body]

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

           Summary: mod_mem_cache update of headers in cache object isn't
                    atomic
           Product: Apache httpd-2
           Version: 2.2.8
          Platform: PC
        OS/Version: Linux
            Status: NEW
          Severity: normal
          Priority: P2
         Component: mod_cache
        AssignedTo: bugs@httpd.apache.org
        ReportedBy: blucia@gmail.com


I am using mod_mem_cache with the worker MPM.  Using a profiling tool for
detecting certain interleavings between the code of concurrently executing
threads, I have discovered that headers which actually end up being cached may
have originated partially from 1 thread, and partially from another. 
Specifically, look at the following code:

   mobj->req_hdrs = deep_table_copy(mobj->pool, r->headers_in);
   /* Precompute how much storage we need to hold the headers */
   headers_out = ap_cache_cacheable_hdrs_out(r->pool, r->headers_out,
                                             r->server);
   /* If not set in headers_out, set Content-Type */
   if (!apr_table_get(headers_out, "Content-Type")
       && r->content_type) {
       apr_table_setn(headers_out, "Content-Type",
                      ap_make_content_type(r, r->content_type)); 
   }
   headers_out = apr_table_overlay(r->pool, headers_out, r->err_headers_out);
   mobj->header_out = deep_table_copy(mobj->pool, headers_out);


Here, the mobj->req_hdrs are assigned to the deep_table_copy result, which is
based on r->headers_in.  After a short while, mobj->header_out is assigned to
the deep_table_copy of the headers_out object (which is computed from
r->headers_out).  Under heavy load (~100 concurrent requests), while this is
happening in one thread (T1, say), it can be (and likely is) happening
concurrently in another (T2, say).  So:  between when T1 writes mobj->req_hdrs,
and when T1 writes mobj->header_out, T2 is able to preempt T1, and write
mobj->req_hdrs and mobj->header_out.  The sequence of events is as follows:

T1: Write mobj->req_hdrs
T2: Write mobj->req_hdrs
T2: Write mobj->header_out
T1: Write mobj->header_out

This results in mobj->req_hdrs being the version written by the request being
processed in T1, and mobj->header_out being the version written by the request
being processed in T2.  Depending on the nature of the requests being issued,
this could result in an inconsistent pair of headers being stored in the cached
object.


-- 
Configure bugmail: https://issues.apache.org/bugzilla/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
You are the assignee for the bug.

---------------------------------------------------------------------
To unsubscribe, e-mail: bugs-unsubscribe@httpd.apache.org
For additional commands, e-mail: bugs-help@httpd.apache.org

[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic