From c0c64621e64db8abcc43408e64aa3f2a48997b85 Mon Sep 17 00:00:00 2001 From: Bryon Roche Date: Thu, 14 Jul 2016 05:22:25 -0700 Subject: [PATCH] Add a thread-dumping handler Add a 'crier' handler to dump the thread stacks of running threads to the log, for easier debugging. --- headphones/crier.py | 36 ++++++++++++++++++++++++++++++++++++ headphones/webserve.py | 7 ++++++- 2 files changed, 42 insertions(+), 1 deletion(-) create mode 100644 headphones/crier.py diff --git a/headphones/crier.py b/headphones/crier.py new file mode 100644 index 00000000..2399f6a9 --- /dev/null +++ b/headphones/crier.py @@ -0,0 +1,36 @@ +import pprint +import sys +import threading +import traceback + +from headphones import logger + + +def cry(): + """ + Logs thread traces. + """ + tmap = {} + main_thread = None + # get a map of threads by their ID so we can print their names + # during the traceback dump + for t in threading.enumerate(): + if t.ident: + tmap[t.ident] = t + else: + main_thread = t + + # Loop over each thread's current frame, writing info about it + for tid, frame in sys._current_frames().iteritems(): + thread = tmap.get(tid, main_thread) + + lines = [] + lines.append('%s\n' % thread.getName()) + lines.append('========================================\n') + lines += traceback.format_stack(frame) + lines.append('========================================\n') + lines.append('LOCAL VARIABLES:\n') + lines.append('========================================\n') + lines.append(pprint.pformat(frame.f_locals)) + lines.append('\n\n') + logger.info("".join(lines)) diff --git a/headphones/webserve.py b/headphones/webserve.py index f4a06c2b..249bf9f9 100644 --- a/headphones/webserve.py +++ b/headphones/webserve.py @@ -28,7 +28,7 @@ import urllib2 import os import re -from headphones import logger, searcher, db, importer, mb, lastfm, librarysync, helpers, notifiers +from headphones import logger, searcher, db, importer, mb, lastfm, librarysync, helpers, notifiers, crier from headphones.helpers import checked, radio, today, clean_name from mako.lookup import TemplateLookup from mako import exceptions @@ -69,6 +69,11 @@ class WebInterface(object): artists = myDB.select('SELECT * from artists order by ArtistSortName COLLATE NOCASE') return serve_template(templatename="index.html", title="Home", artists=artists) + @cherrypy.expose + def threads(self): + crier.cry() + raise cherrypy.HTTPRedirect("home") + @cherrypy.expose def artistPage(self, ArtistID): myDB = db.DBConnection()