Add support for making Tornado dump its stack via SIGUSR1/2.

With this change,

pkill -SIGUSR1 -f runtornado

will dump the stack and SIGUSR2 will enable an interactive debugging
session.

This fixes #613 for Tornado which was the original motive for that
ticket; I'm not sure whether we want to do this for our Django
processes as well, but it would be easy to do so if we did.

(imported from commit a7de7c6070f4bf0404bed6f434e6a6b291d66a26)
This commit is contained in:
Tim Abbott 2013-03-06 13:28:41 -05:00
parent 97344573ef
commit acab720502
2 changed files with 28 additions and 0 deletions

26
zephyr/lib/debug.py Normal file
View File

@ -0,0 +1,26 @@
import code
import traceback
import signal
# Interactive debugging code from
# http://stackoverflow.com/questions/132058/showing-the-stack-trace-from-a-running-python-application
# (that link also points to code for an interactive remote debugger
# setup, which we might want if we move Tornado to run in a daemon
# rather than via screen).
def interactive_debug(sig, frame):
"""Interrupt running process, and provide a python prompt for
interactive debugging."""
d={'_frame':frame} # Allow access to frame object.
d.update(frame.f_globals) # Unless shadowed by global
d.update(frame.f_locals)
message = "Signal recieved : entering python shell.\nTraceback:\n"
message += ''.join(traceback.format_stack(frame))
i = code.InteractiveConsole(d)
i.interact(message)
# SIGUSR1 => Just print the stack
# SIGUSR2 => Print stack + open interactive debugging shell
def interactive_debug_listen():
signal.signal(signal.SIGUSR1, lambda sig, stack: traceback.print_stack(stack))
signal.signal(signal.SIGUSR2, interactive_debug)

View File

@ -8,6 +8,7 @@ import tornado.web
import logging
import time
from tornado import ioloop
from zephyr.lib.debug import interactive_debug_listen
# A hack to keep track of how much time we spend working, versus sleeping in
# the event loop.
@ -78,6 +79,7 @@ class Command(BaseCommand):
# setup unbuffered I/O
sys.stdout = os.fdopen(sys.stdout.fileno(), 'w', 0)
sys.stderr = os.fdopen(sys.stderr.fileno(), 'w', 0)
interactive_debug_listen()
import django
from django.core.handlers.wsgi import WSGIHandler