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

Skip to content

Commit bfaa79a

Browse files
author
Charles-François Natali
committed
Issue #11867: Make test_mailbox.test_lock_conflict deterministic (and fix a
race condition).
2 parents ca9afca + 78ed83d commit bfaa79a

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):
@@ -993,28 +997,36 @@ def test_add_and_close(self):
993997
self.assertEqual(contents, f.read())
994998
self._box = self._factory(self._path)
995999

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

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

0 commit comments

Comments
 (0)