From ac3a391505117febeccf52b6097f1bc485b729a4 Mon Sep 17 00:00:00 2001 From: ianb Date: Wed, 21 Feb 2007 00:22:13 +0000 Subject: Add tracebacks of each thread under Python 2.5 (thanks to Alexander Schremmer for pointing out the technique) --- paste/debug/watchthreads.py | 62 ++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 58 insertions(+), 4 deletions(-) (limited to 'paste/debug') diff --git a/paste/debug/watchthreads.py b/paste/debug/watchthreads.py index b3260f6..94621d7 100644 --- a/paste/debug/watchthreads.py +++ b/paste/debug/watchthreads.py @@ -2,8 +2,11 @@ Watches the key ``paste.httpserver.thread_pool`` to see how many threads there are and report on any wedged threads. """ +import sys import cgi import time +import traceback +from cStringIO import StringIO from thread import get_ident from paste import httpexceptions from paste.request import construct_url, parse_formvars @@ -37,6 +40,21 @@ page_template = HTMLTemplate(''' background-color: #006; color: #fff; } + a.button { + background-color: #ddd; + border: #aaa outset 2px; + text-decoration: none; + margin-top: 10px; + font-size: 80%; + color: #000; + } + a.button:hover { + background-color: #eee; + border: #bbb outset 2px; + } + a.button:active { + border: #bbb inset 2px; + } {{title}} @@ -85,18 +103,18 @@ page_template = HTMLTemplate(''' - Show environ + ">▸ Show environ + + {{if thread.traceback}} + ▸ Show traceback + + + {{endif}} + @@ -170,6 +208,7 @@ class WatchThreads(object): thread.time_html = format_time(now-time_started) thread.uri_short = shorten(thread.uri) thread.environ = worker_environ + thread.traceback = traceback_thread(thread_id) page = page_template.substitute( title="Thread Pool Worker Tracker", @@ -203,6 +242,21 @@ class WatchThreads(object): headers=[('Location', script_name+'?kill=%s' % thread_id)]) return exc(environ, start_response) +def traceback_thread(thread_id): + """ + Returns a plain-text traceback of the given thread, or None if it + can't get a traceback. + """ + if not hasattr(sys, '_current_frames'): + # Only 2.5 has support for this, with this special function + return None + frames = sys._current_frames() + if not thread_id in frames: + return None + frame = frames[thread_id] + out = StringIO() + traceback.print_stack(frame, file=out) + return out.getvalue() hide_keys = ['paste.httpserver.thread_pool'] -- cgit v1.2.1