/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
  <jgoerzen@complete.org> Tue, 6 May 2003 09:21:38 -0500
This commit is contained in:
jgoerzen 2003-05-06 20:26:12 +01:00
parent 4ab1ebf4a8
commit b36c52d5af
2 changed files with 42 additions and 11 deletions

View File

@ -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 <jgoerzen@complete.org> Tue, 6 May 2003 07:25:38 -0500
offlineimap (3.99.16) unstable; urgency=low offlineimap (3.99.16) unstable; urgency=low
* This is a 4.0 TRACK release, and may be unstable or in flux! * This is a 4.0 TRACK release, and may be unstable or in flux!

View File

@ -18,6 +18,8 @@
from Base import BaseFolder from Base import BaseFolder
from offlineimap import imaputil from offlineimap import imaputil
from offlineimap.ui import UIBase
from threading import Lock
import os.path, os, re, time, socket, md5 import os.path, os, re, time, socket, md5
foldermatchre = re.compile(',FMD5=([0-9a-f]{32})') foldermatchre = re.compile(',FMD5=([0-9a-f]{32})')
@ -26,17 +28,22 @@ flagmatchre = re.compile(':.*2,([A-Z]+)')
timeseq = 0 timeseq = 0
lasttime = long(0) lasttime = long(0)
timelock = Lock()
def gettimeseq(): def gettimeseq():
global lasttime, timeseq global lasttime, timeseq, timelock
thistime = long(time.time()) timelock.acquire()
if thistime == lasttime: try:
timeseq += 1 thistime = long(time.time())
return timeseq if thistime == lasttime:
else: timeseq += 1
lasttime = long(time.time()) return (thistime, timeseq)
timeseq = 0 else:
return timeseq lasttime = thistime
timeseq = 0
return (thistime, timeseq)
finally:
timelock.release()
class MaildirFolder(BaseFolder): class MaildirFolder(BaseFolder):
def __init__(self, root, name, sep, repository, accountname): def __init__(self, root, name, sep, repository, accountname):
@ -118,6 +125,9 @@ class MaildirFolder(BaseFolder):
return retval.replace("\r\n", "\n") return retval.replace("\r\n", "\n")
def savemessage(self, uid, content, flags): 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: if uid < 0:
# We cannot assign a new uid. # We cannot assign a new uid.
return uid return uid
@ -137,9 +147,10 @@ class MaildirFolder(BaseFolder):
while 1: while 1:
if attempts > 15: if attempts > 15:
raise IOError, "Couldn't write to file %s" % messagename raise IOError, "Couldn't write to file %s" % messagename
timeval, timeseq = gettimeseq()
messagename = '%d_%d.%d.%s,U=%d,FMD5=%s' % \ messagename = '%d_%d.%d.%s,U=%d,FMD5=%s' % \
(long(time.time()), (timeval,
gettimeseq(), timeseq,
os.getpid(), os.getpid(),
socket.gethostname(), socket.gethostname(),
uid, uid,
@ -150,15 +161,19 @@ class MaildirFolder(BaseFolder):
else: else:
break break
tmpmessagename = messagename.split(',')[0] tmpmessagename = messagename.split(',')[0]
ui.debug('maildir', 'savemessage: using temporary name %s' % tmpmessagename)
file = open(os.path.join(tmpdir, tmpmessagename), "wt") file = open(os.path.join(tmpdir, tmpmessagename), "wt")
file.write(content) file.write(content)
file.close() file.close()
ui.debug('maildir', 'savemessage: moving from %s to %s' % \
(tmpmessagename, messagename))
os.link(os.path.join(tmpdir, tmpmessagename), os.link(os.path.join(tmpdir, tmpmessagename),
os.path.join(newdir, messagename)) os.path.join(newdir, messagename))
os.unlink(os.path.join(tmpdir, tmpmessagename)) os.unlink(os.path.join(tmpdir, tmpmessagename))
self.messagelist[uid] = {'uid': uid, 'flags': [], self.messagelist[uid] = {'uid': uid, 'flags': [],
'filename': os.path.join(newdir, messagename)} 'filename': os.path.join(newdir, messagename)}
self.savemessageflags(uid, flags) self.savemessageflags(uid, flags)
ui.debug('maildir', 'savemessage: returning uid %d' % uid)
return uid return uid
def getmessageflags(self, uid): def getmessageflags(self, uid):