UIDMaps: correctly protect from concurrent writes

Signed-off-by: Nicolas Sebrecht <nicolas.s-dev@laposte.net>
This commit is contained in:
Nicolas Sebrecht 2016-06-28 15:38:35 +02:00
parent cd43cd5b3b
commit 296c8a6146

View File

@ -77,10 +77,19 @@ class MappedIMAPFolder(IMAPFolder):
def _savemaps(self): def _savemaps(self):
mapfilename = self._getmapfilename() mapfilename = self._getmapfilename()
with open(mapfilename + ".tmp", 'wt') as mapfilefd: mapfilenamelock = "%s.lock"% mapfilename
for (key, value) in self.diskl2r.items(): with open(mapfilenamelock, 'w') as mapfilelock:
mapfilefd.write("%d:%d\n"% (key, value)) # The "account" lock already prevents from multiple access by
os.rename(mapfilename + '.tmp', mapfilename) # different processes. However, we still need to protect for
# multiple access from different threads.
try:
fnctl.lockf(mapfilelock, fnctl.LOCK_EX) # Blocks until acquired.
except NameError:
pass # Windows...
with open(mapfilename, 'wt') as mapfilefd:
for (key, value) in self.diskl2r.items():
mapfilefd.write("%d:%d\n"% (key, value))
# The lock is released when the file descriptor ends.
def _uidlist(self, mapping, items): def _uidlist(self, mapping, items):
try: try: