[PATCHv2 4b/2] Implement true single-threading
Sebastian Spaeth
Sebastian at SSpaeth.de
Mon Jan 10 11:12:43 GMT 2011
Previously, we would spawn child threads for account synchronization
even if we had single-threading enabled. This prevented us from catching
the true location of exceptions, for example. Now, in single-threaded
mode, we perform the account synchronization truely in the main thread
which will ease our debugging.
Signed-off-by: Sebastian Spaeth <Sebastian at SSpaeth.de>
---
This is version 2, part b of the patch 4 that it replaces. As noted,
the previous patch 4 led to nonworking code due to a mixup with my
import statements. I took care to only modify code that actually
implemented single threading, so this one should be smaller, cleaner
and more self-contained. Also this version only invokes
single-threading when we call offlineimap with the "-1" singlethreading
option. We will do the multithreading as before when there is only a
single account to sync or syncmaxaccounts is set to 1 (default). We can
discuss in the future if these cases should also fall under the
single-threaded code path.
offlineimap/init.py | 39 ++++++++++++++++++++++++++++-----------
offlineimap/syncmaster.py | 4 +---
2 files changed, 29 insertions(+), 14 deletions(-)
diff --git a/offlineimap/init.py b/offlineimap/init.py
index f652328..9c39e8d 100644
--- a/offlineimap/init.py
+++ b/offlineimap/init.py
@@ -293,11 +293,8 @@ class OfflineImap:
remoterepos = None
localrepos = None
- if options.singlethreading:
- threadutil.initInstanceLimit("ACCOUNTLIMIT", 1)
- else:
- threadutil.initInstanceLimit("ACCOUNTLIMIT",
- config.getdefaultint("general", "maxsyncaccounts", 1))
+ threadutil.initInstanceLimit("ACCOUNTLIMIT",
+ config.getdefaultint("general", "maxsyncaccounts", 1))
for reposname in config.getsectionlist('Repository'):
for instancename in ["FOLDER_" + reposname,
@@ -326,15 +323,23 @@ class OfflineImap:
signal.signal(signal.SIGUSR1,sig_handler)
signal.signal(signal.SIGUSR2,sig_handler)
- threadutil.initexitnotify()
- t = threadutil.ExitNotifyThread(target=syncmaster.syncitall,
+ #various initializations that need to be performed:
+ threadutil.initexitnotify() #TODO: Why?
+ offlineimap.mbnames.init(config, syncaccounts)
+
+ if options.singlethreading:
+ #singlethreaded
+ self.sync_singlethreaded(syncaccounts, config, siglisteners)
+ else:
+ # multithreaded
+ t = threadutil.ExitNotifyThread(target=syncmaster.syncitall,
name='Sync Runner',
kwargs = {'accounts': syncaccounts,
'config': config,
'siglisteners': siglisteners})
- t.setDaemon(1)
- t.start()
- threadutil.exitnotifymonitorloop(threadutil.threadexited)
+ t.setDaemon(1)
+ t.start()
+ threadutil.exitnotifymonitorloop(threadutil.threadexited)
except KeyboardInterrupt:
ui.terminate(1, errormsg = 'CTRL-C pressed, aborting...')
@@ -344,4 +349,16 @@ class OfflineImap:
except:
ui.mainException()
-
+ def sync_singlethreaded(self, accs, config, siglisteners):
+ """Executed if we do not want a separate syncmaster thread
+
+ :param accs: A list of accounts that should be synced
+ :param config: The CustomConfig object
+ :param siglisteners: The signal listeners list, defined in run()
+ """
+ for accountname in accs:
+ account = offlineimap.accounts.SyncableAccount(config, accountname)
+ siglistener = offlineimap.accounts.SigListener()
+ siglisteners.append(siglistener)
+ threading.currentThread().name = "Account sync %s" % accountname
+ account.syncrunner(siglistener=siglistener)
diff --git a/offlineimap/syncmaster.py b/offlineimap/syncmaster.py
index 2da8e3e..5a0a2fb 100644
--- a/offlineimap/syncmaster.py
+++ b/offlineimap/syncmaster.py
@@ -16,7 +16,6 @@
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
-from offlineimap import mbnames
from offlineimap.threadutil import threadlist, InstanceLimitedThread, ExitNotifyThread
from offlineimap.accounts import SyncableAccount, SigListener
from threading import currentThread
@@ -33,11 +32,10 @@ def syncaccount(threads, config, accountname, siglisteners):
thread.setDaemon(1)
thread.start()
threads.add(thread)
-
+
def syncitall(accounts, config, siglisteners):
currentThread().setExitMessage('SYNC_WITH_TIMER_TERMINATE')
threads = threadlist()
- mbnames.init(config, accounts)
for accountname in accounts:
syncaccount(threads, config, accountname, siglisteners)
# Wait for the threads to finish.
--
1.7.1
More information about the OfflineIMAP-project
mailing list