I have found an incomplete-initialization bug the WSGIHandler when running under Apache mpm_worker with mod_wsgi.
On the first request the WSGIHandler.__call__(...), we set up the middleware. There is a lock wrapping the load of the middleware, but the logic still allows incomplete initialization on other threads. Below is the block of code in question from django/core/handlers/wsgi.py (line 226): if self._request_middleware is None: self.initLock.acquire() # Check that middleware is still uninitialised. if self._request_middleware is None: self.load_middleware() self.initLock.release() Example: 1. Initial start or restart of the Apache instance 2. Thread T1 - a request comes in. self._request_middleware is None 3. Thread T1 - acquires the self.initLock, calls self.load_middleware() 4. Thread T2 - a request comes in (T1 is part of the way through self.load_middleware() 5. Thread T2 - self._request_middleware is not None, but it's not completely loaded either, continues with the request 6. Thread T1 - completes self.load_middleware(), release the lock The problem is the assignment of self._request_middleware is not atomic (it is created as an empty list and populated with append() in a loop. To fix this, we need an atomic assignment. I initially thought about changing load_middleware() to build the _request_middleware array in a local variable and then doing a single assignment to save it to self._request_middleware. While this would solve the problem, I thought that having the initialization test in WSGIHandler.__call__() test for what is essentially a side effect of self.load_middleware() is error prone. So, my proposed fix is to add a flag in WSGIHandler and then test for that flag in __call__(). I implemented this in our custom WSGI handler replacement and it worked perfectly. I will submit a ticket with patch to Django if the group agrees. Here is my fix: WSGIHandler.__init__(self): BaseHandler.__init__(self) self._middleware_loaded = False WSGIHandler.__call__(...): ... if not self._middleware_loaded: self.initLock.acquire() # Check that middleware is still uninitialised. if not self._middleware_loaded: self.load_middleware() self._middleware_loaded = True self.initLock.release() ... Travis Propeller.com --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Django developers" group. To post to this group, send email to django-developers@googlegroups.com To unsubscribe from this group, send email to django-developers+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/django-developers?hl=en -~----------~----~----~----~------~----~------~--~---