Issue #11867: Make test_mailbox.test_lock_conflict deterministic (and fix a

race condition).
parent 62f3d030
...@@ -17,6 +17,10 @@ try: ...@@ -17,6 +17,10 @@ try:
import fcntl import fcntl
except ImportError: except ImportError:
pass pass
try:
import multiprocessing
except ImportError:
multiprocessing = None
class TestBase(unittest.TestCase): class TestBase(unittest.TestCase):
...@@ -994,28 +998,36 @@ class _TestMboxMMDF(TestMailbox): ...@@ -994,28 +998,36 @@ class _TestMboxMMDF(TestMailbox):
self.assertEqual(contents, f.read()) self.assertEqual(contents, f.read())
self._box = self._factory(self._path) 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): def test_lock_conflict(self):
# Fork off a subprocess that will lock the file for 2 seconds, # Fork off a child process that will lock the mailbox temporarily,
# unlock it, and then exit. # unlock it and exit.
if not hasattr(os, 'fork'): ready = multiprocessing.Event()
return done = multiprocessing.Event()
pid = os.fork() pid = os.fork()
if pid == 0: if pid == 0:
# In the child, lock the mailbox. # child
try: try:
# lock the mailbox, and signal the parent it can proceed
self._box.lock() self._box.lock()
time.sleep(2) ready.set()
# wait until the parent is done, and unlock the mailbox
done.wait(5)
self._box.unlock() self._box.unlock()
finally: finally:
os._exit(0) os._exit(0)
# In the parent, sleep a bit to give the child time to acquire # In the parent, wait until the child signals it locked the mailbox.
# the lock. ready.wait(5)
time.sleep(0.5)
try: try:
self.assertRaises(mailbox.ExternalClashError, self.assertRaises(mailbox.ExternalClashError,
self._box.lock) self._box.lock)
finally: finally:
# Signal the child it can now release the lock and exit.
done.set()
# Wait for child to exit. Locking should now succeed. # Wait for child to exit. Locking should now succeed.
exited_pid, status = os.waitpid(pid, 0) exited_pid, status = os.waitpid(pid, 0)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment