From 09a2ac922133096b501222911dd3f077fadc0347 Mon Sep 17 00:00:00 2001 From: jgoerzen Date: Thu, 17 Oct 2002 00:27:27 +0100 Subject: [PATCH] /offlineimap/head: changeset 272 When an exception occurs, OfflineIMAP will attempt to print the last 50 debug messages, whether or not debugging was enabled for this session. This way, even unexpected and non-repeatable errors stand a chance of getting a more detailed log. --- offlineimap/head/debian/changelog | 4 ++ offlineimap/head/offlineimap/ui/Tk.py | 17 ++++---- offlineimap/head/offlineimap/ui/UIBase.py | 49 +++++++++++++++++++---- 3 files changed, 54 insertions(+), 16 deletions(-) diff --git a/offlineimap/head/debian/changelog b/offlineimap/head/debian/changelog index 1cf5d4f..e14a1c8 100644 --- a/offlineimap/head/debian/changelog +++ b/offlineimap/head/debian/changelog @@ -1,6 +1,10 @@ offlineimap (3.99.2) unstable; urgency=low * Further attempts to fix imapsplit problems. + * When an exception occurs, OfflineIMAP will attempt to print the last + 50 debug messages, whether or not debugging was enabled for this + session. This way, even unexpected and non-repeatable errors stand + a chance of getting a more detailed log. -- John Goerzen Tue, 15 Oct 2002 12:35:42 -0500 diff --git a/offlineimap/head/offlineimap/ui/Tk.py b/offlineimap/head/offlineimap/ui/Tk.py index 4a48571..a4b816b 100644 --- a/offlineimap/head/offlineimap/ui/Tk.py +++ b/offlineimap/head/offlineimap/ui/Tk.py @@ -207,6 +207,7 @@ class VerboseUI(UIBase): s.availablethreadframes.append(tf) del s.threadframes[threadid] s.tflock.release() + UIBase.threadExited(s, thread) def idlevacuum(s): while s.notdeleted: @@ -218,24 +219,22 @@ class VerboseUI(UIBase): s.tflock.release() def threadException(s, thread): - msg = "Thread '%s' terminated with exception:\n%s" % \ - (thread.getName(), thread.getExitStackTrace()) - print msg + exceptionstr = s.getThreadExceptionString(thread) + print exceptionstr s.top.destroy() s.top = None - TextOKDialog("Thread Exception", msg) + TextOKDialog("Thread Exception", exceptionstr) + s.delThreadDebugLog(thread) s.terminate(100) def mainException(s): - sbuf = StringIO() - traceback.print_exc(file = sbuf) - msg = "Main program terminated with exception:\n" + sbuf.getvalue() - print msg + exceptionstr = s.getMainExceptionString() + print exceptionstr s.top.destroy() s.top = None - TextOKDialog("Main Program Exception", msg) + TextOKDialog("Main Program Exception", exceptionstr) def warn(s, msg): TextOKDialog("OfflineIMAP Warning", msg) diff --git a/offlineimap/head/offlineimap/ui/UIBase.py b/offlineimap/head/offlineimap/ui/UIBase.py index 27a820a..43107f8 100644 --- a/offlineimap/head/offlineimap/ui/UIBase.py +++ b/offlineimap/head/offlineimap/ui/UIBase.py @@ -17,7 +17,7 @@ # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA import offlineimap.version -import re, time, sys, traceback +import re, time, sys, traceback, threading from StringIO import StringIO debugtypes = {'imap': 'IMAP protocol debugging', @@ -36,6 +36,8 @@ class UIBase: s.verbose = verbose s.config = config s.debuglist = [] + s.debugmessages = {} + s.debugmsglen = 50 ################################################## UTILS def _msg(s, msg): @@ -46,6 +48,15 @@ class UIBase: s._msg("WARNING: " + msg) def debug(s, debugtype, msg): + thisthread = threading.currentThread() + if s.debugmessages.has_key(thisthread): + s.debugmessages[thisthread].append("%s: %s" % (debugtype, msg)) + else: + s.debugmessages[thisthread] = ["%s: %s" % (debugtype, msg)] + + while len(s.debugmessages[thisthread]) > s.debugmsglen: + s.debugmessages[thisthread] = s.debugmessages[thisthread][1:] + if debugtype in s.debuglist: s._msg("DEBUG[%s]: %s" % (debugtype, msg)) @@ -195,18 +206,42 @@ class UIBase: ################################################## Threads + def getThreadDebugLog(s, thread): + if s.debugmessages.has_key(thread): + message = "\nLast %d debug messages logged for %s prior to exception:\n"\ + % (len(s.debugmessages[thread]), thread.getName()) + message += "\n".join(s.debugmessages[thread]) + else: + message = "\nNo debug messages were logged for %s." % \ + thread.getName() + return message + + def delThreadDebugLog(s, thread): + if s.debugmessages.has_key(thread): + del s.debugmessages[thread] + + def getThreadExceptionString(s, thread): + message = "Thread '%s' terminated with exception:\n%s" % \ + (thread.getName(), thread.getExitStackTrace()) + message += "\n" + s.getThreadDebugLog(thread) + return message + def threadException(s, thread): """Called when a thread has terminated with an exception. The argument is the ExitNotifyThread that has so terminated.""" - s._msg("Thread '%s' terminated with exception:\n%s" % \ - (thread.getName(), thread.getExitStackTrace())) + s._msg(s.getThreadExceptionString(thread)) + s.delThreadDebugLog(thread) s.terminate(100) - def mainException(s): + def getMainExceptionString(s): sbuf = StringIO() traceback.print_exc(file = sbuf) - s._msg("Main program terminated with exception:\n" + - sbuf.getvalue()) + return "Main program terminated with exception:\n" + \ + sbuf.getvalue() + "\n" + \ + s.getThreadDebugLog(threading.currentThread()) + + def mainException(s): + s._msg(s.getMainExceptionString()) def terminate(s, exitstatus = 0): """Called to terminate the application.""" @@ -215,7 +250,7 @@ class UIBase: def threadExited(s, thread): """Called when a thread has exited normally. Many UIs will just ignore this.""" - pass + s.delThreadDebugLog(thread) ################################################## Other