From b36c52d5afe6158e19fbe5705577c85e3f20e680 Mon Sep 17 00:00:00 2001 From: jgoerzen Date: Tue, 6 May 2003 20:26:12 +0100 Subject: [PATCH] /offlineimap/head: changeset 474 - offlineimap (3.99.17) unstable; urgency=low - Fixed two potential obscure race conditions in folder/Maildir.py. + Condition 1 involved the gettimeseq() function. This function accesses per-module variables but does not have a lock. It may have been possible for this to have been called in such a way that timeseq was not properly updated. + Condition 2 involved the call to gettimeseq(). Since the timeseq is based on the system clock, we now use the time as reported inside timeseq() rather than outside. This way, we can be assured that the same value is in use both places. - Added debug code to savemessage in folder/Maildir.py to try to track down a mysterious 0-length file bug. -- John Goerzen Tue, 6 May 2003 09:21:38 -0500 --- offlineimap/head/debian/changelog | 16 ++++++++ .../head/offlineimap/folder/Maildir.py | 37 +++++++++++++------ 2 files changed, 42 insertions(+), 11 deletions(-) diff --git a/offlineimap/head/debian/changelog b/offlineimap/head/debian/changelog index ef6f384..3ce9413 100644 --- a/offlineimap/head/debian/changelog +++ b/offlineimap/head/debian/changelog @@ -1,3 +1,19 @@ +offlineimap (3.99.17) unstable; urgency=low + + * Fixed two potential obscure race conditions in folder/Maildir.py. + + Condition 1 involved the gettimeseq() function. This function + accesses per-module variables but does not have a lock. It may have + been possible for this to have been called in such a way that timeseq + was not properly updated. + + Condition 2 involved the call to gettimeseq(). Since the timeseq is + based on the system clock, we now use the time as reported inside + timeseq() rather than outside. This way, we can be assured that the + same value is in use both places. + * Added debug code to savemessage in folder/Maildir.py to try to track + down a mysterious 0-length file bug. + + -- John Goerzen Tue, 6 May 2003 07:25:38 -0500 + offlineimap (3.99.16) unstable; urgency=low * This is a 4.0 TRACK release, and may be unstable or in flux! diff --git a/offlineimap/head/offlineimap/folder/Maildir.py b/offlineimap/head/offlineimap/folder/Maildir.py index 71d73fc..69cb033 100644 --- a/offlineimap/head/offlineimap/folder/Maildir.py +++ b/offlineimap/head/offlineimap/folder/Maildir.py @@ -18,6 +18,8 @@ from Base import BaseFolder from offlineimap import imaputil +from offlineimap.ui import UIBase +from threading import Lock import os.path, os, re, time, socket, md5 foldermatchre = re.compile(',FMD5=([0-9a-f]{32})') @@ -26,17 +28,22 @@ flagmatchre = re.compile(':.*2,([A-Z]+)') timeseq = 0 lasttime = long(0) +timelock = Lock() def gettimeseq(): - global lasttime, timeseq - thistime = long(time.time()) - if thistime == lasttime: - timeseq += 1 - return timeseq - else: - lasttime = long(time.time()) - timeseq = 0 - return timeseq + global lasttime, timeseq, timelock + timelock.acquire() + try: + thistime = long(time.time()) + if thistime == lasttime: + timeseq += 1 + return (thistime, timeseq) + else: + lasttime = thistime + timeseq = 0 + return (thistime, timeseq) + finally: + timelock.release() class MaildirFolder(BaseFolder): def __init__(self, root, name, sep, repository, accountname): @@ -118,6 +125,9 @@ class MaildirFolder(BaseFolder): return retval.replace("\r\n", "\n") def savemessage(self, uid, content, flags): + ui = UIBase.getglobalui() + ui.debug('maildir', 'savemessage: called to write with flags %s and content %s' % \ + (repr(flags), repr(content))) if uid < 0: # We cannot assign a new uid. return uid @@ -137,9 +147,10 @@ class MaildirFolder(BaseFolder): while 1: if attempts > 15: raise IOError, "Couldn't write to file %s" % messagename + timeval, timeseq = gettimeseq() messagename = '%d_%d.%d.%s,U=%d,FMD5=%s' % \ - (long(time.time()), - gettimeseq(), + (timeval, + timeseq, os.getpid(), socket.gethostname(), uid, @@ -150,15 +161,19 @@ class MaildirFolder(BaseFolder): else: break tmpmessagename = messagename.split(',')[0] + ui.debug('maildir', 'savemessage: using temporary name %s' % tmpmessagename) file = open(os.path.join(tmpdir, tmpmessagename), "wt") file.write(content) file.close() + ui.debug('maildir', 'savemessage: moving from %s to %s' % \ + (tmpmessagename, messagename)) os.link(os.path.join(tmpdir, tmpmessagename), os.path.join(newdir, messagename)) os.unlink(os.path.join(tmpdir, tmpmessagename)) self.messagelist[uid] = {'uid': uid, 'flags': [], 'filename': os.path.join(newdir, messagename)} self.savemessageflags(uid, flags) + ui.debug('maildir', 'savemessage: returning uid %d' % uid) return uid def getmessageflags(self, uid):