Issue #11867: Make test_mailbox.test_lock_conflict deterministic (and fix a
race condition).
This commit is contained in:
parent
62f3d0300e
commit
78ed83da46
|
@ -17,6 +17,10 @@ try:
|
|||
import fcntl
|
||||
except ImportError:
|
||||
pass
|
||||
try:
|
||||
import multiprocessing
|
||||
except ImportError:
|
||||
multiprocessing = None
|
||||
|
||||
|
||||
class TestBase(unittest.TestCase):
|
||||
|
@ -994,28 +998,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.
|
||||
# child
|
||||
try:
|
||||
# lock the mailbox, and signal the parent it can proceed
|
||||
self._box.lock()
|
||||
time.sleep(2)
|
||||
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, sleep a bit to give the child time to acquire
|
||||
# the lock.
|
||||
time.sleep(0.5)
|
||||
# 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)
|
||||
|
||||
|
|
Loading…
Reference in New Issue