bpo-40094: Enhance threading tests (GH-19260)
https://github.com/python/cpython/commit/a9f9687a7ce25e7c0c89f88f52db3231046... commit: a9f9687a7ce25e7c0c89f88f52db323104668ae0 branch: master author: Victor Stinner <vstinner@python.org> committer: GitHub <noreply@github.com> date: 2020-03-31T21:49:44+02:00 summary: 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. files: M Lib/test/test_thread.py M Lib/test/test_threading.py diff --git a/Lib/test/test_thread.py b/Lib/test/test_thread.py index 9f4801f47e3aa..77e46f2c2f15a 100644 --- a/Lib/test/test_thread.py +++ b/Lib/test/test_thread.py @@ -225,30 +225,31 @@ def setUp(self): @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 da17e1281d986..8a4efd647096a 100644 --- a/Lib/test/test_threading.py +++ b/Lib/test/test_threading.py @@ -485,9 +485,7 @@ def test_is_alive_after_fork(self): 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 @@ def f(): 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 @@ def test_main_thread_after_fork(self): 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 @@ def test_main_thread_after_fork(self): 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 @@ def f(): # 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 @@ def test_1_join_on_shutdown(self): 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 @@ def test_3_join_in_forked_from_thread(self): # 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 @@ def do_fork_and_wait(): # 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 @@ def test_clear_threads_states_after_fork(self): 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()
participants (1)
-
Victor Stinner