[3.6] bpo-31234: Enhance test_thread.test_forkinthread() (GH-3516) (#3519)
* test_thread.test_forkinthread() now waits until the thread completes. * Check the status in the test method, not in the thread function * Don't ignore RuntimeError anymore: since the commit346cbd351e
(bpo-16500, os.register_at_fork(), os.fork() cannot fail anymore with RuntimeError. * Replace 0.01 literal with a new POLL_SLEEP constant * test_forkinthread(): test if os.fork() exists rather than testing the platform. (cherry picked from commita15d155aad
)
This commit is contained in:
parent
c0e77364ca
commit
bcf042ff98
|
@ -11,6 +11,7 @@ from test import lock_tests
|
||||||
|
|
||||||
NUMTASKS = 10
|
NUMTASKS = 10
|
||||||
NUMTRIPS = 3
|
NUMTRIPS = 3
|
||||||
|
POLL_SLEEP = 0.010 # seconds = 10 ms
|
||||||
|
|
||||||
_print_mutex = thread.allocate_lock()
|
_print_mutex = thread.allocate_lock()
|
||||||
|
|
||||||
|
@ -114,7 +115,7 @@ class ThreadRunningTests(BasicThreadTest):
|
||||||
mut.release()
|
mut.release()
|
||||||
thread.start_new_thread(task, ())
|
thread.start_new_thread(task, ())
|
||||||
while not started:
|
while not started:
|
||||||
time.sleep(0.01)
|
time.sleep(POLL_SLEEP)
|
||||||
self.assertEqual(thread._count(), orig + 1)
|
self.assertEqual(thread._count(), orig + 1)
|
||||||
# Allow the task to finish.
|
# Allow the task to finish.
|
||||||
mut.release()
|
mut.release()
|
||||||
|
@ -125,7 +126,7 @@ class ThreadRunningTests(BasicThreadTest):
|
||||||
wr = weakref.ref(task, lambda _: done.append(None))
|
wr = weakref.ref(task, lambda _: done.append(None))
|
||||||
del task
|
del task
|
||||||
while not done:
|
while not done:
|
||||||
time.sleep(0.01)
|
time.sleep(POLL_SLEEP)
|
||||||
self.assertEqual(thread._count(), orig)
|
self.assertEqual(thread._count(), orig)
|
||||||
|
|
||||||
def test_save_exception_state_on_error(self):
|
def test_save_exception_state_on_error(self):
|
||||||
|
@ -148,7 +149,7 @@ class ThreadRunningTests(BasicThreadTest):
|
||||||
thread.start_new_thread(task, ())
|
thread.start_new_thread(task, ())
|
||||||
started.acquire()
|
started.acquire()
|
||||||
while thread._count() > c:
|
while thread._count() > c:
|
||||||
time.sleep(0.01)
|
time.sleep(POLL_SLEEP)
|
||||||
self.assertIn("Traceback", stderr.getvalue())
|
self.assertIn("Traceback", stderr.getvalue())
|
||||||
|
|
||||||
|
|
||||||
|
@ -221,30 +222,36 @@ class TestForkInThread(unittest.TestCase):
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
self.read_fd, self.write_fd = os.pipe()
|
self.read_fd, self.write_fd = os.pipe()
|
||||||
|
|
||||||
@unittest.skipIf(sys.platform.startswith('win'),
|
@unittest.skipUnless(hasattr(os, 'fork'), 'need os.fork')
|
||||||
"This test is only appropriate for POSIX-like systems.")
|
|
||||||
@support.reap_threads
|
@support.reap_threads
|
||||||
def test_forkinthread(self):
|
def test_forkinthread(self):
|
||||||
def thread1():
|
running = True
|
||||||
try:
|
status = "not set"
|
||||||
pid = os.fork() # fork in a thread
|
|
||||||
except RuntimeError:
|
|
||||||
os._exit(1) # exit the child
|
|
||||||
|
|
||||||
if pid == 0: # child
|
def thread1():
|
||||||
|
nonlocal running, status
|
||||||
|
|
||||||
|
# fork in a thread
|
||||||
|
pid = os.fork()
|
||||||
|
if pid == 0:
|
||||||
|
# child
|
||||||
try:
|
try:
|
||||||
os.close(self.read_fd)
|
os.close(self.read_fd)
|
||||||
os.write(self.write_fd, b"OK")
|
os.write(self.write_fd, b"OK")
|
||||||
finally:
|
finally:
|
||||||
os._exit(0)
|
os._exit(0)
|
||||||
else: # parent
|
else:
|
||||||
|
# parent
|
||||||
os.close(self.write_fd)
|
os.close(self.write_fd)
|
||||||
pid, status = os.waitpid(pid, 0)
|
pid, status = os.waitpid(pid, 0)
|
||||||
self.assertEqual(status, 0)
|
running = False
|
||||||
|
|
||||||
thread.start_new_thread(thread1, ())
|
thread.start_new_thread(thread1, ())
|
||||||
self.assertEqual(os.read(self.read_fd, 2), b"OK",
|
self.assertEqual(os.read(self.read_fd, 2), b"OK",
|
||||||
"Unable to fork() in thread")
|
"Unable to fork() in thread")
|
||||||
|
while running:
|
||||||
|
time.sleep(POLL_SLEEP)
|
||||||
|
self.assertEqual(status, 0)
|
||||||
|
|
||||||
def tearDown(self):
|
def tearDown(self):
|
||||||
try:
|
try:
|
||||||
|
|
Loading…
Reference in New Issue