summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndrew M. Kuchling <amk@amk.ca>2006-11-17 13:30:25 (GMT)
committerAndrew M. Kuchling <amk@amk.ca>2006-11-17 13:30:25 (GMT)
commit8c456f3b5705f9b4dc8f822f92185570c1ce94bb (patch)
tree7bd3f8cd29c8ee77550fef80d215066df8a387ca
parent25aabf4cbb7ff8d1a38f8ef4602a409c00474a30 (diff)
downloadcpython-8c456f3b5705f9b4dc8f822f92185570c1ce94bb.zip
cpython-8c456f3b5705f9b4dc8f822f92185570c1ce94bb.tar.gz
cpython-8c456f3b5705f9b4dc8f822f92185570c1ce94bb.tar.bz2
Remove file-locking in MH.pack() method.
This change looks massive but it's mostly a re-indenting after removing some try...finally blocks. Also adds a test case that does a pack() while the mailbox is locked; this test would have turned up bugs in the original code on some platforms. In both nmh and GNU Mailutils' implementation of MH-format mailboxes, no locking is done of individual message files when renaming them. The original mailbox.py code did do locking, which meant that message files had to be opened. This code was buggy on certain platforms (found through reading the code); there were code paths that closed the file object and then called _unlock_file() on it. Will backport to 25-maint once I see how the buildbots react to this patch.
-rwxr-xr-xLib/mailbox.py28
-rw-r--r--Lib/test/test_mailbox.py15
2 files changed, 22 insertions, 21 deletions
diff --git a/Lib/mailbox.py b/Lib/mailbox.py
index c6b0fa0..108d874 100755
--- a/Lib/mailbox.py
+++ b/Lib/mailbox.py
@@ -1054,27 +1054,13 @@ class MH(Mailbox):
for key in self.iterkeys():
if key - 1 != prev:
changes.append((key, prev + 1))
- f = open(os.path.join(self._path, str(key)), 'r+')
- try:
- if self._locked:
- _lock_file(f)
- try:
- if hasattr(os, 'link'):
- os.link(os.path.join(self._path, str(key)),
- os.path.join(self._path, str(prev + 1)))
- if sys.platform == 'os2emx':
- # cannot unlink an open file on OS/2
- f.close()
- os.unlink(os.path.join(self._path, str(key)))
- else:
- f.close()
- os.rename(os.path.join(self._path, str(key)),
- os.path.join(self._path, str(prev + 1)))
- finally:
- if self._locked:
- _unlock_file(f)
- finally:
- f.close()
+ if hasattr(os, 'link'):
+ os.link(os.path.join(self._path, str(key)),
+ os.path.join(self._path, str(prev + 1)))
+ os.unlink(os.path.join(self._path, str(key)))
+ else:
+ os.rename(os.path.join(self._path, str(key)),
+ os.path.join(self._path, str(prev + 1)))
prev += 1
self._next_key = prev + 1
if len(changes) == 0:
diff --git a/Lib/test/test_mailbox.py b/Lib/test/test_mailbox.py
index 2434dbc..97270d0 100644
--- a/Lib/test/test_mailbox.py
+++ b/Lib/test/test_mailbox.py
@@ -887,6 +887,21 @@ class TestMH(TestMailbox):
self.assert_(self._box.get_sequences() ==
{'foo':[1, 2, 3], 'unseen':[1], 'bar':[3], 'replied':[3]})
+ # Test case for packing while holding the mailbox locked.
+ key0 = self._box.add(msg1)
+ key1 = self._box.add(msg1)
+ key2 = self._box.add(msg1)
+ key3 = self._box.add(msg1)
+
+ self._box.remove(key0)
+ self._box.remove(key2)
+ self._box.lock()
+ self._box.pack()
+ self._box.unlock()
+ self.assert_(self._box.get_sequences() ==
+ {'foo':[1, 2, 3, 4, 5],
+ 'unseen':[1], 'bar':[3], 'replied':[3]})
+
def _get_lock_path(self):
return os.path.join(self._path, '.mh_sequences.lock')