Reputation: 11571
I am maintaining a django project that gets unresponsive on regular basis. So far I dealt with the situation by continuously monitoring the application and restarting apache when necessary.
Unresponsive how? It means that apache does not reply to any request anymore.
The environment:
What can I do to get closer to the root of the error? (I cannot not provide the source code - snippets here and there are possible though) I've hunted this problem for so long that it is impossible to list all the things I tried. I tried to get rid of any 'magic' that I could think of. Several parts of the application have been rewritten since the problem occurred.
I am sorry for the lack of detail, but I'll happily provide (almost) any information that is requested and promise to do my best to make this post as helpful as possible to others facing similar problems.
Upvotes: 1
Views: 2658
Reputation: 1922
You might be bitten by the following django bug [1] (that is not yet fixed in 1.4 branch)
workaround: manuall apply the fix to your django sources, or use a threadsafe wrapper around the the wsgi module as shown below (we use this in production systems)
from __future__ import with_statement
from django.core.handlers.wsgi import WSGIHandler as DjangoWSGIHandler
from threading import Lock
__copyright__ = "Jibe"
class WSGIHandler(DjangoWSGIHandler):
"""
This provides a threadsafe drop-in replacement of django's WSGIHandler.
Initialisation of django via a multithreaded wsgi handler is not safe.
It is vulnerable to a A-B B-A deadlock.
When two threads bootstrap django via different urls you have a change to hit
the following deadlock.
thread 1 thread 2
view A view B
import file foo import lock foo import file bar import lock bar
bootstrap django lock AppCache.write_lock
import file bar import lock bar <-- blocks
bootstrap django lock AppCache.write_lock <----- deadlock
workaround for an AB BA deadlock: wrap it in a lock C.
lock C lock C
lock A lock B
lock B lock A
release B release A
release A release A
release C release C
Thats exactly what this class does, but... only for the first few calls.
After that we remove the lock C. as the AppCache.write_lock is only held when django is booted.
If we would not remove the lock C after the first few calls, that would make the whole app single threaded again.
Usage:
in your wsgi file replace the following lines
import django.core.handlers.wsgi.WSGIHandler
application = django.core.handlers.wsgi.WSGIHandler
by
import threadsafe_wsgi
application = threadsafe_wsgi.WSGIHandler
FAQ:
Q: why would you want threading in the first place ?
A: to reduce memory. Big apps can consume hundeds of megabytes each. adding processes is then much more expensive than threads.
that memory is better spend caching, when threads are almost free.
Q: this deadlock, it looks far-fetched, is this real ?
A: yes we had this problem on production machines.
"""
__initLock = Lock() # lock C
__initialized = 0
def __call__(self, environ, start_response):
# the first calls (4) we squeeze everybody through lock C
# this basically serializes all threads
MIN_INIT_CALLS = 4
if self.__initialized < MIN_INIT_CALLS:
with self.__initLock:
ret = DjangoWSGIHandler.__call__(self, environ, start_response)
self.__initialized += 1
return ret
else:
# we are safely bootrapped, skip lock C
# now we are running multi-threaded again
return DjangoWSGIHandler.__call__(self, environ, start_response)
and in your wsgi.py
use the following code
from threadsafe_wsgi.handlers import WSGIHandler
django_handler = WSGIHandler()
[1] https://code.djangoproject.com/ticket/18251
Upvotes: 1
Reputation: 58563
Ultimately you need the new features that have been added to mod_wsgi 4.0. These will allow for daemon mode better control over automatic restarts when requests block. When restarting upon blocked condition mod_wsgi will attempt to dump out Python stack traces for what each of the Python request threads was doing at the time so you can see why they are blocked.
Suggest you take up the issue on the mod_wsgi mailing list and can explain the new features in more detail if need be. Have posted before about it at:
http://groups.google.com/group/modwsgi/msg/2a968d820e18e97d
The mod_wsgi 4.0 code is only available from source code repository at this time. Current trunk head believed to be stable.
Upvotes: 2