DO NOT REPLY TO THIS EMAIL, BUT PLEASE POST YOUR BUGĀ·
RELATED COMMENTS THROUGH THE WEB INTERFACE AVAILABLE AT
<https://issues.apache.org/bugzilla/show_bug.cgi?id=44402>.
ANY REPLY MADE TO THIS MESSAGE WILL NOT BE COLLECTED ANDĀ·
INSERTED IN THE BUG DATABASE.

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





------- Additional Comments From [EMAIL PROTECTED]  2008-02-22 12:28 -------
Created an attachment (id=21581)
 --> (https://issues.apache.org/bugzilla/attachment.cgi?id=21581&action=view)
Patch for httpd-2.2.8

Eventually I figured out where is the real race condition.

Lines fdqueue.c:96-102 (in httpd-2.2.8)
        for (;;) {
            new_recycle->next = queue_info->recycled_pools;
            if (apr_atomic_casptr((volatile
void**)&(queue_info->recycled_pools),
                                  new_recycle, new_recycle->next) ==
                new_recycle->next) {
                break;
            }
        }

The race condition is between return of apr_atomic_casptr and calculating
new_recycle->next.

Let us write the look into three steps (qi->rp is queue_info->recycled_pools):
1. Set new_recycle->next to qi->rp
2. atomically compare and swap qi->rp with new_recycle if matches with
    new_recycle->next.
3. Calculate new_recycle->next again.
4. Determine the call apr_atomic_casptr is successful based on the return value
and
   result of step 3.

The race condition is in between step2 and step3. If apr_atomic_casptr was
successful (it means it successfully swapped the value) and If there is a
context switch between 2 and 3 then new_recycle->next can point to something
else and can also be corrupted. The result of which is that if condition will
fail.

I saved the new_recycle->next in a local variable and then used the local
variable as shown in the patch and the issue got resolved.

Here is the example how new_recycle->next can be changed by a race condition :
Suppose our list is 1-->2-->3, where 1,2,3 are list nodes. Now suppose worker
thread 1 wants to add a node 4 to it's head. Here is how it goes :

-----------------------------------------------------------
Worker thread 1 :
   new_recycle = 4;
   qi->rp = 1;
   new_recycle->next = 1;
   apr_atomic_casptr successfully compare and swap it with qi->rp that means
   qi->rp = 4; 
   (list now becomes 4-->1-->2-->3)

   Now context switch happens :

Listener_thread : 
   qi->rp is 4 and hence it pops the node 4 and gives it to worker thread 2.
   The list becomes 1-->2-->3.

   Listener thread pops another node and give it worker thread 3 and now list
   becomes 2-->3.

Worker thread 2 :
   Returns the node 4 into the list and list becomes 4-->2-->3.

Worker thread 1 :
   new_recycle->next now becomes 2 and it compares with 1 and hence
comparision fails.
-----------------------------------------------------------

   Real situations can be little different than what I described because before

worker thread returns node 4 to the list, pool is cleared (line 897 of
worker.c,
in worker_thread function )
        apr_pool_clear(ptrans);
        last_ptrans = ptrans;

which means new_recycle->next will be corrupted and point to a deleted value.

How I figured out this is that if you put a assert statement like :
            struct recycled_pool *next = queue_info->recycled_pools;
            new_recycle->next = next;
            if (apr_atomic_casptr((volatile
void**)&(queue_info->recycled_pools),
                                  new_recycle, new_recycle->next) == next) {
                ap_assert(next == new_recycle->next);
                break;
            }
then assertion fails under stress situations.

The bug also exist in event mpm too (server/mpm/experimental/event/fdqueue.c).

Ruediger, can you review the patch? The patch is against 2.2.8. Should I submit

patch against trunk?


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

---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to