summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVictor Stinner <vstinner@python.org>2020-03-31 19:49:44 (GMT)
committerGitHub <noreply@github.com>2020-03-31 19:49:44 (GMT)
commita9f9687a7ce25e7c0c89f88f52db323104668ae0 (patch)
tree0049f147ffb3311373bb5a5501457d73796e7474
parent27c6231f5827fe17c6cb6f097391931f30b511ec (diff)
downloadcpython-a9f9687a7ce25e7c0c89f88f52db323104668ae0.zip
cpython-a9f9687a7ce25e7c0c89f88f52db323104668ae0.tar.gz
cpython-a9f9687a7ce25e7c0c89f88f52db323104668ae0.tar.bz2
bpo-40094: Enhance threading tests (GH-19260)
* Rewrite test_thread.test_forkinthread() to use support.wait_process() and wait for the child process in the main thread, not in the spawned thread. * test_threading now uses support.wait_process() and checks the child process exit code to detect crashes.
-rw-r--r--Lib/test/test_thread.py37
-rw-r--r--Lib/test/test_threading.py33
2 files changed, 39 insertions, 31 deletions
diff --git a/Lib/test/test_thread.py b/Lib/test/test_thread.py
index 9f4801f..77e46f2 100644
--- a/Lib/test/test_thread.py
+++ b/Lib/test/test_thread.py
@@ -225,30 +225,31 @@ class TestForkInThread(unittest.TestCase):
@unittest.skipUnless(hasattr(os, 'fork'), 'need os.fork')
@support.reap_threads
def test_forkinthread(self):
- status = "not set"
+ pid = None
- def thread1():
- nonlocal status
+ def fork_thread(read_fd, write_fd):
+ nonlocal pid
# fork in a thread
pid = os.fork()
- if pid == 0:
- # child
- try:
- os.close(self.read_fd)
- os.write(self.write_fd, b"OK")
- finally:
- os._exit(0)
- else:
- # parent
- os.close(self.write_fd)
- pid, status = os.waitpid(pid, 0)
+ if pid:
+ # parent process
+ return
+
+ # child process
+ try:
+ os.close(read_fd)
+ os.write(write_fd, b"OK")
+ finally:
+ os._exit(0)
with support.wait_threads_exit():
- thread.start_new_thread(thread1, ())
- self.assertEqual(os.read(self.read_fd, 2), b"OK",
- "Unable to fork() in thread")
- self.assertEqual(status, 0)
+ thread.start_new_thread(fork_thread, (self.read_fd, self.write_fd))
+ self.assertEqual(os.read(self.read_fd, 2), b"OK")
+ os.close(self.write_fd)
+
+ self.assertIsNotNone(pid)
+ support.wait_process(pid, exitcode=0)
def tearDown(self):
try:
diff --git a/Lib/test/test_threading.py b/Lib/test/test_threading.py
index da17e12..8a4efd6 100644
--- a/Lib/test/test_threading.py
+++ b/Lib/test/test_threading.py
@@ -485,9 +485,7 @@ class ThreadTests(BaseTestCase):
else:
t.join()
- pid, status = os.waitpid(pid, 0)
- self.assertTrue(os.WIFEXITED(status))
- self.assertEqual(10, os.WEXITSTATUS(status))
+ support.wait_process(pid, exitcode=10)
def test_main_thread(self):
main = threading.main_thread()
@@ -507,6 +505,7 @@ class ThreadTests(BaseTestCase):
def test_main_thread_after_fork(self):
code = """if 1:
import os, threading
+ from test import support
pid = os.fork()
if pid == 0:
@@ -515,7 +514,7 @@ class ThreadTests(BaseTestCase):
print(main.ident == threading.current_thread().ident)
print(main.ident == threading.get_ident())
else:
- os.waitpid(pid, 0)
+ support.wait_process(pid, exitcode=0)
"""
_, out, err = assert_python_ok("-c", code)
data = out.decode().replace('\r', '')
@@ -528,6 +527,7 @@ class ThreadTests(BaseTestCase):
def test_main_thread_after_fork_from_nonmain_thread(self):
code = """if 1:
import os, threading, sys
+ from test import support
def f():
pid = os.fork()
@@ -540,7 +540,7 @@ class ThreadTests(BaseTestCase):
# we have to flush before exit.
sys.stdout.flush()
else:
- os.waitpid(pid, 0)
+ support.wait_process(pid, exitcode=0)
th = threading.Thread(target=f)
th.start()
@@ -813,11 +813,15 @@ class ThreadJoinOnShutdown(BaseTestCase):
def test_2_join_in_forked_process(self):
# Like the test above, but from a forked interpreter
script = """if 1:
+ from test import support
+
childpid = os.fork()
if childpid != 0:
- os.waitpid(childpid, 0)
+ # parent process
+ support.wait_process(childpid, exitcode=0)
sys.exit(0)
+ # child process
t = threading.Thread(target=joiningfunc,
args=(threading.current_thread(),))
t.start()
@@ -832,13 +836,17 @@ class ThreadJoinOnShutdown(BaseTestCase):
# In the forked process, the main Thread object must be marked as stopped.
script = """if 1:
+ from test import support
+
main_thread = threading.current_thread()
def worker():
childpid = os.fork()
if childpid != 0:
- os.waitpid(childpid, 0)
+ # parent process
+ support.wait_process(childpid, exitcode=0)
sys.exit(0)
+ # child process
t = threading.Thread(target=joiningfunc,
args=(main_thread,))
print('end of main')
@@ -901,9 +909,9 @@ class ThreadJoinOnShutdown(BaseTestCase):
# just fork a child process and wait it
pid = os.fork()
if pid > 0:
- os.waitpid(pid, 0)
+ support.wait_process(pid, exitcode=50)
else:
- os._exit(0)
+ os._exit(50)
# start a bunch of threads that will fork() child processes
threads = []
@@ -930,12 +938,11 @@ class ThreadJoinOnShutdown(BaseTestCase):
if pid == 0:
# check that threads states have been cleared
if len(sys._current_frames()) == 1:
- os._exit(0)
+ os._exit(51)
else:
- os._exit(1)
+ os._exit(52)
else:
- _, status = os.waitpid(pid, 0)
- self.assertEqual(0, status)
+ support.wait_process(pid, exitcode=51)
for t in threads:
t.join()