I have found an incomplete-initialization bug the WSGIHandler when running under Apache mpm_worker with mod_wsgi. Code review shows this is a potential problem with all of the handlers.
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:
- Initial start or restart of the Apache instance
- Thread T1 - a request comes in. self._request_middleware is None
- Thread T1 - acquires the self.initLock, calls self.load_middleware()
- Thread T2 - a request comes in (T1 is part of the way through self.load_middleware())
- Thread T2 - self._request_middleware is not None, but it's not completely loaded either, continues with the request
- Thread T1 - completes self.load_middleware(), release the lock
The attached patch changes BaseHandler.load_middleware() to do an atomic set of all four middleware lists. self._request_middleware is set last to signal the completion of middleware loading.