From 8970a1500b6b85c7f0c3a9e2c112e63261d2d120 Mon Sep 17 00:00:00 2001 From: Sebastian Spaeth Date: Thu, 29 Sep 2011 15:43:01 +0200 Subject: [PATCH] UIBase: Fix and cleanup register/unregisterthread Registering a thread (associating it with a certain account name) would fail if it was already registered. However, as we a) never unregister most threads (bad) and b) single-threaded mode reuses threads, we failed when syncing multiple accounts in single-threading mode. This commit cleans up the functions to not make re-registering a thread fatal (it could be legitimate, however it *should* not occur). Future work needs to be done to unregister new threads at the appropriate places. Signed-off-by: Sebastian Spaeth --- Changelog.draft.rst | 4 ++++ offlineimap/ui/UIBase.py | 42 ++++++++++++++++++++++------------------ 2 files changed, 27 insertions(+), 19 deletions(-) diff --git a/Changelog.draft.rst b/Changelog.draft.rst index b532734..7ced439 100644 --- a/Changelog.draft.rst +++ b/Changelog.draft.rst @@ -18,3 +18,7 @@ Changes Bug Fixes --------- + +* Syncing multiple accounts in single-threaded mode would fail as we try + to "register" a thread as belonging to two accounts which was + fatal. Make it non-fatal (it can be legitimate). diff --git a/offlineimap/ui/UIBase.py b/offlineimap/ui/UIBase.py index 52b1788..77594f2 100644 --- a/offlineimap/ui/UIBase.py +++ b/offlineimap/ui/UIBase.py @@ -47,6 +47,7 @@ class UIBase: s.debugmessages = {} s.debugmsglen = 50 s.threadaccounts = {} + """dict linking active threads (k) to account names (v)""" s.logfile = None s.exc_queue = Queue() """saves all occuring exceptions, so we can output them at the end""" @@ -117,29 +118,32 @@ class UIBase: if exc_traceback: self._msg(traceback.format_tb(exc_traceback)) - def registerthread(s, account): - """Provides a hint to UIs about which account this particular - thread is processing.""" - if s.threadaccounts.has_key(threading.currentThread()): - raise ValueError, "Thread %s already registered (old %s, new %s)" %\ - (threading.currentThread().getName(), - s.getthreadaccount(s), account) - s.threadaccounts[threading.currentThread()] = account - s.debug('thread', "Register new thread '%s' (account '%s')" %\ - (threading.currentThread().getName(), account)) + def registerthread(self, account): + """Register current thread as being associated with an account name""" + cur_thread = threading.currentThread() + if cur_thread in self.threadaccounts: + # was already associated with an old account, update info + self.debug('thread', "Register thread '%s' (previously '%s', now " + "'%s')" % (cur_thread.getName(), + self.getthreadaccount(cur_thread), account)) + else: + self.debug('thread', "Register new thread '%s' (account '%s')" %\ + (cur_thread.getName(), account)) + self.threadaccounts[cur_thread] = account - def unregisterthread(s, thr): - """Recognizes a thread has exited.""" - if s.threadaccounts.has_key(thr): - del s.threadaccounts[thr] - s.debug('thread', "Unregister thread '%s'" % thr.getName()) + def unregisterthread(self, thr): + """Unregister a thread as being associated with an account name""" + if self.threadaccounts.has_key(thr): + del self.threadaccounts[thr] + self.debug('thread', "Unregister thread '%s'" % thr.getName()) - def getthreadaccount(s, thr = None): + def getthreadaccount(self, thr = None): + """Get name of account for a thread (current if None)""" if not thr: thr = threading.currentThread() - if s.threadaccounts.has_key(thr): - return s.threadaccounts[thr] - return '*Control' + if thr in self.threadaccounts: + return self.threadaccounts[thr] + return '*Control' # unregistered thread is '*Control' def debug(s, debugtype, msg): thisthread = threading.currentThread()