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. :-( --Brian
[EMAIL PROTECTED] 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.
Ryan
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.
--Brian
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 + size;
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?
Sander
_____________________________________________________________________________ Ryan Bloom [EMAIL PROTECTED] Covalent Technologies [EMAIL PROTECTED] -----------------------------------------------------------------------------
