apr-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Brian Pane <bp...@pacbell.net>
Subject Re: Possible race condition in pools WAS: RE: Thoughts on locks
Date Thu, 28 Jun 2001 02:46:25 GMT
Assuming that fixing it with code would mean adding a lock around
that block in apr_palloc, I submit that fixing it with documentation
is the better option.  Given how much slower the threaded MPM is
than the prefork one right now, I think that adding more mutex overhead
would be bad. :-(

rbb@covalent.net wrote:

>This is correct.  Most of the locking in pools was based on the fact that
>Apache doesn't have this type of problem.  We can either fix the problem
>with code or docs, but it does need to be fixed.
>On Wed, 27 Jun 2001, Brian Pane wrote:
>>Yes, there's definitely a race condition there.  I noticed that
>>too, and I thought it was intentional (i.e., that the lack of a
>>lock was a conscious choice to avoid a performance penalty
>>for apps in which pools aren't shared across threads) and
>>harmless (because there aren't any pools in Apache shared
>>by multiple threads that can do apr_palloc).  But if the
>>non-thread-safety is intentional, there probably should be
>>a prominent warning about it in the include file and documentation.
>>Sander Striker wrote:
>>>>In the current apr_palloc, the lock is only around the call to new_block.
>>>>I think that's reasonable; new_block is manipulating a global
>>>>free list, so it has to be mutex-protected.
>>>This triggered me to investigate the pools code again. It seems to me that
>>>there is a possible race condition when two threads share the same pool.
>>>Examine the following piece of code that is not protected by a lock:
>>>   ...
>>>   new_first_avail = first_avail + size;
>>>   if (new_first_avail <= blok->h.endp) {
>>>       debug_verify_filled(first_avail, blok->h.endp,
>>>                           "[apr_palloc] Ouch!  Someone trounced past the
>>>end "
>>>                           "of their allocation!\n");
>>>       blok->h.first_avail = new_first_avail;
>>>       return (void *) first_avail;
>>>   }
>>>   ...
>>>Now in a situation with 2 threads that call apr_palloc at the same time
>>>(both requesting a size that fits the last block):
>>>    A                                       B
>>>T1   new_first_avail = first_avail + size;
>>>T2                                           new_first_avail = first_avail +
>>>Now, the test will succeed in both A and B, effectively returning the same
>>>memory twice:
>>>    if (new_first_avail <= blok->h.endp) {
>>>        blok->h.first_avail = new_first_avail;
>>>        return (void *) first_avail;
>>>    }
>>>Or am I missing something?
>Ryan Bloom                        	rbb@apache.org
>Covalent Technologies			rbb@covalent.net

View raw message