From 35acb3597208e10a101140474adec86859d57f61 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Wed, 18 Dec 2019 10:11:05 +0100 Subject: bpo-38546: multiprocessing tests stop the resource tracker (GH-17641) (GH-17647) Multiprocessing and concurrent.futures tests now stop the resource tracker process when tests complete. Add ResourceTracker._stop() method to multiprocessing.resource_tracker. Add _cleanup_tests() helper function to multiprocessing.util: share code between multiprocessing and concurrent.futures tests. (cherry picked from commit 9707e8e22d80ca97bf7a9812816701cecde6d226) --- Lib/multiprocessing/resource_tracker.py | 13 +++++++++++ Lib/multiprocessing/util.py | 25 ++++++++++++++++++++++ Lib/test/_test_multiprocessing.py | 11 +--------- Lib/test/test_concurrent_futures.py | 12 +---------- .../Tests/2019-12-17-15-27-07.bpo-38546.82JwN2.rst | 2 ++ 5 files changed, 42 insertions(+), 21 deletions(-) create mode 100644 Misc/NEWS.d/next/Tests/2019-12-17-15-27-07.bpo-38546.82JwN2.rst diff --git a/Lib/multiprocessing/resource_tracker.py b/Lib/multiprocessing/resource_tracker.py index 61a6dd6..c9bfa9b 100644 --- a/Lib/multiprocessing/resource_tracker.py +++ b/Lib/multiprocessing/resource_tracker.py @@ -50,6 +50,19 @@ class ResourceTracker(object): self._fd = None self._pid = None + def _stop(self): + with self._lock: + if self._fd is None: + # not running + return + + # closing the "alive" file descriptor stops main() + os.close(self._fd) + self._fd = None + + os.waitpid(self._pid, 0) + self._pid = None + def getfd(self): self.ensure_running() return self._fd diff --git a/Lib/multiprocessing/util.py b/Lib/multiprocessing/util.py index 32b51b0..745f2b2 100644 --- a/Lib/multiprocessing/util.py +++ b/Lib/multiprocessing/util.py @@ -439,3 +439,28 @@ def close_fds(*fds): """Close each file descriptor given as an argument""" for fd in fds: os.close(fd) + + +def _cleanup_tests(): + """Cleanup multiprocessing resources when multiprocessing tests + completed.""" + + from test import support + + # cleanup multiprocessing + process._cleanup() + + # Stop the ForkServer process if it's running + from multiprocessing import forkserver + forkserver._forkserver._stop() + + # Stop the ResourceTracker process if it's running + from multiprocessing import resource_tracker + resource_tracker._resource_tracker._stop() + + # bpo-37421: Explicitly call _run_finalizers() to remove immediately + # temporary directories created by multiprocessing.util.get_temp_dir(). + _run_finalizers() + support.gc_collect() + + support.reap_children() diff --git a/Lib/test/_test_multiprocessing.py b/Lib/test/_test_multiprocessing.py index b7f3d25..983770f 100644 --- a/Lib/test/_test_multiprocessing.py +++ b/Lib/test/_test_multiprocessing.py @@ -5673,16 +5673,7 @@ def install_tests_in_module_dict(remote_globs, start_method): if need_sleep: time.sleep(0.5) - multiprocessing.process._cleanup() - - # Stop the ForkServer process if it's running - from multiprocessing import forkserver - forkserver._forkserver._stop() - - # bpo-37421: Explicitly call _run_finalizers() to remove immediately - # temporary directories created by multiprocessing.util.get_temp_dir(). - multiprocessing.util._run_finalizers() - test.support.gc_collect() + multiprocessing.util._cleanup_tests() remote_globs['setUpModule'] = setUpModule remote_globs['tearDownModule'] = tearDownModule diff --git a/Lib/test/test_concurrent_futures.py b/Lib/test/test_concurrent_futures.py index 98c9bc9..e01f2e4 100644 --- a/Lib/test/test_concurrent_futures.py +++ b/Lib/test/test_concurrent_futures.py @@ -1306,17 +1306,7 @@ def setUpModule(): def tearDownModule(): test.support.threading_cleanup(*_threads_key) - test.support.reap_children() - - # cleanup multiprocessing - multiprocessing.process._cleanup() - # Stop the ForkServer process if it's running - from multiprocessing import forkserver - forkserver._forkserver._stop() - # bpo-37421: Explicitly call _run_finalizers() to remove immediately - # temporary directories created by multiprocessing.util.get_temp_dir(). - multiprocessing.util._run_finalizers() - test.support.gc_collect() + multiprocessing.util._cleanup_tests() if __name__ == "__main__": diff --git a/Misc/NEWS.d/next/Tests/2019-12-17-15-27-07.bpo-38546.82JwN2.rst b/Misc/NEWS.d/next/Tests/2019-12-17-15-27-07.bpo-38546.82JwN2.rst new file mode 100644 index 0000000..78d9df3 --- /dev/null +++ b/Misc/NEWS.d/next/Tests/2019-12-17-15-27-07.bpo-38546.82JwN2.rst @@ -0,0 +1,2 @@ +Multiprocessing and concurrent.futures tests now stop the resource tracker +process when tests complete. -- cgit v0.12