# This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU Library General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. # # Copyright 2005 Dan Williams and Red Hat, Inc. import sys import SocketServer import traceback import os import threading import thread import time haveThreadframe = True try: import threadframe except ImportError: haveThreadframe = False tlLock = threading.Lock() threadList = {} def registerThreadName(t): name = t.getName() if name and len(name) > 0: tlLock.acquire() threadList[thread.get_ident()] = name tlLock.release() class ThreadTracebackRequestHandler(SocketServer.StreamRequestHandler): def handle(self): if not haveThreadframe: self.wfile.write("Threadframe not installed. No traceback available.") return # Python 2.2 does not support threadframe.dict() if sys.version_info[:3] < (2, 3, 0): frames = threadframe.threadframe() for frame in frames: self.wfile.write(('-' * 72) + '\n') self.wfile.write('frame ref count = %d\n' % sys.getrefcount(frame)) traceback.print_stack(f=frame, limit=None, file=self.wfile) self.wfile.write("\n") else: frames = threadframe.dict() for thread_id, frame in frames.iteritems(): tlLock.acquire() thread_name = '' try: thread_name = " (%s)" % threadList[thread_id] except: pass tlLock.release() self.wfile.write(('-' * 72) + '\n') self.wfile.write('[%s%s] %d' % (thread_id, thread_name, sys.getrefcount(frame))) traceback.print_stack(frame, limit=None, file=self.wfile) self.wfile.write("\n") class ThreadTracebackServer(threading.Thread): def __init__(self, address="/tmp/plague-debug"): if os.path.exists(address): os.remove(address) self._address = address self._server = SocketServer.ThreadingUnixStreamServer(address, ThreadTracebackRequestHandler) self._stop = False threading.Thread.__init__(self) self.setName("DebugUtilsTracebackServer") def run(self): print "Starting traceback server on %s." % self._address registerThreadName(self) while not self._stop: self._server.handle_request() def stop(self): self._stop = True self._server.server_close() def main(): address = "/tmp/plague-debug" server = ThreadTracebackServer(address) server.start() while True: try: time.sleep(1) except KeyboardInterrupt: server.stop() print "Exiting..." os._exit(0) if __name__ == '__main__': main()