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]
