Skip to content

Commit

Permalink
UIBase: Fix and cleanup register/unregisterthread
Browse files Browse the repository at this point in the history
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 <Sebastian@SSpaeth.de>
  • Loading branch information
spaetz committed Sep 29, 2011
1 parent b506684 commit 8970a15
Show file tree
Hide file tree
Showing 2 changed files with 29 additions and 21 deletions.
4 changes: 4 additions & 0 deletions Changelog.draft.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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).
46 changes: 25 additions & 21 deletions offlineimap/ui/UIBase.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ def __init__(s, config, verbose = 0):
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"""
Expand Down Expand Up @@ -117,29 +118,32 @@ def error(self, exc, exc_traceback=None, msg=None):
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 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 getthreadaccount(s, thr = None):
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(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(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()
Expand Down

0 comments on commit 8970a15

Please sign in to comment.