diff options
author | ianb <devnull@localhost> | 2007-02-21 00:22:13 +0000 |
---|---|---|
committer | ianb <devnull@localhost> | 2007-02-21 00:22:13 +0000 |
commit | ac3a391505117febeccf52b6097f1bc485b729a4 (patch) | |
tree | b54920b21afdc372db8d1d74fde02c99f93ed366 /paste/debug | |
parent | 3317c08db036ffbfe6c6f96530d6e9d8b05c34d6 (diff) | |
download | paste-ac3a391505117febeccf52b6097f1bc485b729a4.tar.gz |
Add tracebacks of each thread under Python 2.5 (thanks to Alexander Schremmer for pointing out the technique)
Diffstat (limited to 'paste/debug')
-rw-r--r-- | paste/debug/watchthreads.py | 62 |
1 files changed, 58 insertions, 4 deletions
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; + } </style> <title>{{title}}</title> </head> @@ -85,18 +103,18 @@ page_template = HTMLTemplate(''' </td> <tr> <td colspan="2" class="bottom"> - <a href="#" + <a href="#" class="button" style="width: 9em; display: block" onclick=" var el = document.getElementById('environ-{{thread.thread_id}}'); if (el.style.display) { el.style.display = ''; - this.innerHTML = 'Hide environ'; + this.innerHTML = '▾ Hide environ'; } else { el.style.display = 'none'; - this.innerHTML = 'Show environ'; + this.innerHTML = '▸ Show environ'; } return false - ">Show environ</a> + ">▸ Show environ</a> <div id="environ-{{thread.thread_id}}" style="display: none"> <table class="environ"> @@ -109,6 +127,26 @@ page_template = HTMLTemplate(''' {{endfor}} </table> </div> + + {{if thread.traceback}} + <a href="#" class="button" style="width: 9em; display: block" + onclick=" + var el = document.getElementById('traceback-{{thread.thread_id}}'); + if (el.style.display) { + el.style.display = ''; + this.innerHTML = '▾ Hide traceback'; + } else { + el.style.display = 'none'; + this.innerHTML = '▸ Show traceback'; + } + return false + ">▸ Show traceback</a> + + <div id="traceback-{{thread.thread_id}}" style="display: none"> + <pre class="traceback">{{thread.traceback}}</pre> + </div> + {{endif}} + </td> </tr> </table> @@ -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'] |