gh-84559: Change the multiprocessing start method default to forkserver (GH-101556)

Change the default multiprocessing start method away from fork to forkserver or spawn on the remaining platforms where it was fork.  See the issue for context.  This makes the default far more thread safe (other than for people spawning threads at import time... - don't do that!).

Co-authored-by: blurb-it[bot] <43283697+blurb-it[bot]@users.noreply.github.com>
Co-authored-by: Hugo van Kemenade <1324225+hugovk@users.noreply.github.com>
This commit is contained in:
Gregory P. Smith 2024-09-26 16:57:19 -07:00 committed by GitHub
parent 83e5dc0f4d
commit b65f2cdfa7
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 75 additions and 33 deletions

View file

@ -5553,15 +5553,29 @@ class TestStartMethod(unittest.TestCase):
multiprocessing.set_start_method(old_method, force=True)
self.assertGreaterEqual(count, 1)
def test_get_all(self):
def test_get_all_start_methods(self):
methods = multiprocessing.get_all_start_methods()
self.assertIn('spawn', methods)
if sys.platform == 'win32':
self.assertEqual(methods, ['spawn'])
elif sys.platform == 'darwin':
self.assertEqual(methods[0], 'spawn') # The default is first.
# Whether these work or not, they remain available on macOS.
self.assertIn('fork', methods)
self.assertIn('forkserver', methods)
else:
self.assertTrue(methods == ['fork', 'spawn'] or
methods == ['spawn', 'fork'] or
methods == ['fork', 'spawn', 'forkserver'] or
methods == ['spawn', 'fork', 'forkserver'])
# POSIX
self.assertIn('fork', methods)
if other_methods := set(methods) - {'fork', 'spawn'}:
# If there are more than those two, forkserver must be one.
self.assertEqual({'forkserver'}, other_methods)
# The default is the first method in the list.
self.assertIn(methods[0], {'forkserver', 'spawn'},
msg='3.14+ default must not be fork')
if methods[0] == 'spawn':
# Confirm that the current default selection logic prefers
# forkserver vs spawn when available.
self.assertNotIn('forkserver', methods)
def test_preload_resources(self):
if multiprocessing.get_start_method() != 'forkserver':