I have a problem which I am hoping might be solved with some form of shutdown hook in Django.
I am still a beginner with Python/Django development, and to help learn I have set myself a project of developing a COMET/Reverse Ajax style chat site that runs in browser. The browser continuously polls the server for any messages. When the server receives a poll request, it checks to see if there are any messages waiting, and if there are none, it will attempt to acquire a lock on a threading.Lock object which has already been acquired. This causes the thread which is handling the request to block until a message is received and the previously mentioned lock is released.
My problem arises when I shutdown the server. At this point I am using the development server (python manage.py runserver). If there is a thread blocked from the above explained process, then the server does not shutdown.
Is there a way that i can execute code when the server attempts to shutdown so that i can release any waiting threads?
I have looked at the following similar question however it hasn't helped me. There was speculation that such an event hook does not exist, however no definitive answer. I've googled high and low, but haven't had any luck.
I am using Python 2.7 and Django 1.5.
Grateful for any help you can provide
I don't know of a shutdown event, but you can create one.
When the user presses Ctrl-C, a SIGINT signal is sent to Python process. Setup a signal handler from your wsgi.py
file to catch the SIGINT and forward it to your program.
wsgi.py:
...
import signal
signal.signal(signal.SIGINT, my_signal_handler)
You could even forward the signal to a django signal:
my_django_shutdown_signal = django.dispatch.Signal()
def _forward_to_django_shutdown_signal(signal, frame):
my_django_shutdown_signal.send('system')
sys.exit(0) # So runserver does try to exit
signal.signal(signal.SIGINT, _forward_to_django_shutdown_signal)
Since signal
can only be called from the main thread, this won't work with runserver. Either call runserver with the --noreload
option, or switch over to gunicorn.
Addition to answer by Stu Gla:
To set handler for signal event in main thread in django you can put put initialization of handling to manage.py or your app's __init__.py, like so:
# {project_root}/{your_app}/__init__.py
import os
import signal
import sys
def my_signal_handler(*args):
if os.environ.get('RUN_MAIN') == 'true':
print('stopped'.upper())
sys.exit(0)
signal.signal(signal.SIGINT, my_signal_handler)
It will let you run server without --noreload.
Check for os.environ.get('RUN_MAIN')
pvevent calling function 2 times.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With