Skip to content

Commit 9707e8e

Browse files
authored
bpo-38546: multiprocessing tests stop the resource tracker (GH-17641)
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.
1 parent 630c8df commit 9707e8e

File tree

5 files changed

+42
-21
lines changed

5 files changed

+42
-21
lines changed

Lib/multiprocessing/resource_tracker.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,19 @@ def __init__(self):
5050
self._fd = None
5151
self._pid = None
5252

53+
def _stop(self):
54+
with self._lock:
55+
if self._fd is None:
56+
# not running
57+
return
58+
59+
# closing the "alive" file descriptor stops main()
60+
os.close(self._fd)
61+
self._fd = None
62+
63+
os.waitpid(self._pid, 0)
64+
self._pid = None
65+
5366
def getfd(self):
5467
self.ensure_running()
5568
return self._fd

Lib/multiprocessing/util.py

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -439,3 +439,28 @@ def close_fds(*fds):
439439
"""Close each file descriptor given as an argument"""
440440
for fd in fds:
441441
os.close(fd)
442+
443+
444+
def _cleanup_tests():
445+
"""Cleanup multiprocessing resources when multiprocessing tests
446+
completed."""
447+
448+
from test import support
449+
450+
# cleanup multiprocessing
451+
process._cleanup()
452+
453+
# Stop the ForkServer process if it's running
454+
from multiprocessing import forkserver
455+
forkserver._forkserver._stop()
456+
457+
# Stop the ResourceTracker process if it's running
458+
from multiprocessing import resource_tracker
459+
resource_tracker._resource_tracker._stop()
460+
461+
# bpo-37421: Explicitly call _run_finalizers() to remove immediately
462+
# temporary directories created by multiprocessing.util.get_temp_dir().
463+
_run_finalizers()
464+
support.gc_collect()
465+
466+
support.reap_children()

Lib/test/_test_multiprocessing.py

Lines changed: 1 addition & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -5695,16 +5695,7 @@ def tearDownModule():
56955695
if need_sleep:
56965696
time.sleep(0.5)
56975697

5698-
multiprocessing.process._cleanup()
5699-
5700-
# Stop the ForkServer process if it's running
5701-
from multiprocessing import forkserver
5702-
forkserver._forkserver._stop()
5703-
5704-
# bpo-37421: Explicitly call _run_finalizers() to remove immediately
5705-
# temporary directories created by multiprocessing.util.get_temp_dir().
5706-
multiprocessing.util._run_finalizers()
5707-
test.support.gc_collect()
5698+
multiprocessing.util._cleanup_tests()
57085699

57095700
remote_globs['setUpModule'] = setUpModule
57105701
remote_globs['tearDownModule'] = tearDownModule

Lib/test/test_concurrent_futures.py

Lines changed: 1 addition & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1306,17 +1306,7 @@ def setUpModule():
13061306

13071307
def tearDownModule():
13081308
support.threading_cleanup(*_threads_key)
1309-
support.reap_children()
1310-
1311-
# cleanup multiprocessing
1312-
multiprocessing.process._cleanup()
1313-
# Stop the ForkServer process if it's running
1314-
from multiprocessing import forkserver
1315-
forkserver._forkserver._stop()
1316-
# bpo-37421: Explicitly call _run_finalizers() to remove immediately
1317-
# temporary directories created by multiprocessing.util.get_temp_dir().
1318-
multiprocessing.util._run_finalizers()
1319-
support.gc_collect()
1309+
multiprocessing.util._cleanup_tests()
13201310

13211311

13221312
if __name__ == "__main__":
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Multiprocessing and concurrent.futures tests now stop the resource tracker
2+
process when tests complete.

0 commit comments

Comments
 (0)