Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 78ed83d

Browse files
author
Charles-François Natali
committed
Issue #11867: Make test_mailbox.test_lock_conflict deterministic (and fix a
race condition).
1 parent 62f3d03 commit 78ed83d

1 file changed

Lines changed: 21 additions & 9 deletions

File tree

Lib/test/test_mailbox.py

Lines changed: 21 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,10 @@
1717
import fcntl
1818
except ImportError:
1919
pass
20+
try:
21+
import multiprocessing
22+
except ImportError:
23+
multiprocessing = None
2024

2125

2226
class TestBase(unittest.TestCase):
@@ -994,28 +998,36 @@ def test_add_and_close(self):
994998
self.assertEqual(contents, f.read())
995999
self._box = self._factory(self._path)
9961000

1001+
@unittest.skipUnless(hasattr(os, 'fork'), "Test needs fork().")
1002+
@unittest.skipUnless(multiprocessing, "Test needs multiprocessing.")
9971003
def test_lock_conflict(self):
998-
# Fork off a subprocess that will lock the file for 2 seconds,
999-
# unlock it, and then exit.
1000-
if not hasattr(os, 'fork'):
1001-
return
1004+
# Fork off a child process that will lock the mailbox temporarily,
1005+
# unlock it and exit.
1006+
ready = multiprocessing.Event()
1007+
done = multiprocessing.Event()
1008+
10021009
pid = os.fork()
10031010
if pid == 0:
1004-
# In the child, lock the mailbox.
1011+
# child
10051012
try:
1013+
# lock the mailbox, and signal the parent it can proceed
10061014
self._box.lock()
1007-
time.sleep(2)
1015+
ready.set()
1016+
1017+
# wait until the parent is done, and unlock the mailbox
1018+
done.wait(5)
10081019
self._box.unlock()
10091020
finally:
10101021
os._exit(0)
10111022

1012-
# In the parent, sleep a bit to give the child time to acquire
1013-
# the lock.
1014-
time.sleep(0.5)
1023+
# In the parent, wait until the child signals it locked the mailbox.
1024+
ready.wait(5)
10151025
try:
10161026
self.assertRaises(mailbox.ExternalClashError,
10171027
self._box.lock)
10181028
finally:
1029+
# Signal the child it can now release the lock and exit.
1030+
done.set()
10191031
# Wait for child to exit. Locking should now succeed.
10201032
exited_pid, status = os.waitpid(pid, 0)
10211033

0 commit comments

Comments
 (0)