summaryrefslogtreecommitdiff
path: root/Lib/test/test_mailbox.py
diff options
context:
space:
mode:
authorCharles-François Natali <neologix@free.fr>2011-12-19 12:17:16 +0100
committerCharles-François Natali <neologix@free.fr>2011-12-19 12:17:16 +0100
commit52aa260387e2de3ddf96cc0006867241cd3d3667 (patch)
treeb0ef6b6a4b2946479e86ec285cb71f6e8601ca89 /Lib/test/test_mailbox.py
parent6b7003a18c2fa7378eb5ec5766ded01dee212c85 (diff)
downloadcpython-git-52aa260387e2de3ddf96cc0006867241cd3d3667.tar.gz
Issue #11867: Make test_mailbox.test_lock_conflict deterministic (and fix a
race condition).
Diffstat (limited to 'Lib/test/test_mailbox.py')
-rw-r--r--Lib/test/test_mailbox.py40
1 files changed, 27 insertions, 13 deletions
diff --git a/Lib/test/test_mailbox.py b/Lib/test/test_mailbox.py
index 75e0a8d4f6..9fdcbde0cc 100644
--- a/Lib/test/test_mailbox.py
+++ b/Lib/test/test_mailbox.py
@@ -15,6 +15,10 @@ try:
import fcntl
except ImportError:
pass
+try:
+ import multiprocessing
+except ImportError:
+ multiprocessing = None
# Silence Py3k warning
rfc822 = test_support.import_module('rfc822', deprecated=True)
@@ -865,26 +869,36 @@ class _TestMboxMMDF(TestMailbox):
self.assertEqual(contents, f.read())
self._box = self._factory(self._path)
+ @unittest.skipUnless(hasattr(os, 'fork'), "Test needs fork().")
+ @unittest.skipUnless(multiprocessing, "Test needs multiprocessing.")
def test_lock_conflict(self):
- # Fork off a subprocess that will lock the file for 2 seconds,
- # unlock it, and then exit.
- if not hasattr(os, 'fork'):
- return
+ # Fork off a child process that will lock the mailbox temporarily,
+ # unlock it and exit.
+ ready = multiprocessing.Event()
+ done = multiprocessing.Event()
+
pid = os.fork()
if pid == 0:
- # In the child, lock the mailbox.
- self._box.lock()
- time.sleep(2)
- self._box.unlock()
- os._exit(0)
-
- # In the parent, sleep a bit to give the child time to acquire
- # the lock.
- time.sleep(0.5)
+ # child
+ try:
+ # lock the mailbox, and signal the parent it can proceed
+ self._box.lock()
+ ready.set()
+
+ # wait until the parent is done, and unlock the mailbox
+ done.wait(5)
+ self._box.unlock()
+ finally:
+ os._exit(0)
+
+ # In the parent, wait until the child signals it locked the mailbox.
+ ready.wait(5)
try:
self.assertRaises(mailbox.ExternalClashError,
self._box.lock)
finally:
+ # Signal the child it can now release the lock and exit.
+ done.set()
# Wait for child to exit. Locking should now succeed.
exited_pid, status = os.waitpid(pid, 0)