Add a debug thread that dumps tracebacks.
Start and extra thread that blocks on a threading event until SIGUSR1 is received. Then dump the tracebacks for all threads except itself. This is only really useful as a debug tool for deadlocks, so we might want to hide it behind a flag?
This commit is contained in:
parent
db3a201795
commit
88f0ffb9f2
@ -36,7 +36,7 @@ from mopidy.utils.deps import list_deps_optparse_callback
|
||||
from mopidy.utils.log import setup_logging
|
||||
from mopidy.utils.path import get_or_create_folder, get_or_create_file
|
||||
from mopidy.utils.process import (exit_handler, stop_remaining_actors,
|
||||
stop_actors_by_class)
|
||||
stop_actors_by_class, DebugThread)
|
||||
from mopidy.utils.settings import list_settings_optparse_callback
|
||||
|
||||
|
||||
@ -44,7 +44,12 @@ logger = logging.getLogger('mopidy.main')
|
||||
|
||||
|
||||
def main():
|
||||
debug_thread = DebugThread()
|
||||
debug_thread.start()
|
||||
|
||||
signal.signal(signal.SIGUSR1, debug_thread.handler)
|
||||
signal.signal(signal.SIGTERM, exit_handler)
|
||||
|
||||
loop = gobject.MainLoop()
|
||||
try:
|
||||
options = parse_options()
|
||||
|
||||
@ -1,7 +1,9 @@
|
||||
import logging
|
||||
import signal
|
||||
import sys
|
||||
import thread
|
||||
import threading
|
||||
import traceback
|
||||
|
||||
from pykka import ActorDeadError
|
||||
from pykka.registry import ActorRegistry
|
||||
@ -10,6 +12,9 @@ from mopidy import SettingsError
|
||||
|
||||
logger = logging.getLogger('mopidy.utils.process')
|
||||
|
||||
signals = dict((k, v) for v, k in signal.__dict__.iteritems()
|
||||
if v.startswith('SIG') and not v.startswith('SIG_'))
|
||||
|
||||
def exit_process():
|
||||
logger.debug(u'Interrupting main...')
|
||||
thread.interrupt_main()
|
||||
@ -17,8 +22,6 @@ def exit_process():
|
||||
|
||||
def exit_handler(signum, frame):
|
||||
"""A :mod:`signal` handler which will exit the program on signal."""
|
||||
signals = dict((k, v) for v, k in signal.__dict__.iteritems()
|
||||
if v.startswith('SIG') and not v.startswith('SIG_'))
|
||||
logger.info(u'Got %s signal', signals[signum])
|
||||
exit_process()
|
||||
|
||||
@ -65,3 +68,27 @@ class BaseThread(threading.Thread):
|
||||
|
||||
def run_inside_try(self):
|
||||
raise NotImplementedError
|
||||
|
||||
class DebugThread(threading.Thread):
|
||||
daemon = True
|
||||
name = 'DebugThread'
|
||||
|
||||
event = threading.Event()
|
||||
|
||||
def handler(self, signum, frame):
|
||||
logger.info(u'Got %s signal', signals[signum])
|
||||
self.event.set()
|
||||
|
||||
def run(self):
|
||||
while True:
|
||||
self.event.wait()
|
||||
threads = dict((t.ident, t.name) for t in threading.enumerate())
|
||||
|
||||
for ident, frame in sys._current_frames().items():
|
||||
if self.ident == ident:
|
||||
continue
|
||||
|
||||
print "## Thread: %s (%s) ##" % (threads[ident], ident)
|
||||
print ''.join(traceback.format_stack(frame))
|
||||
|
||||
self.event.clear()
|
||||
|
||||
Loading…
Reference in New Issue
Block a user