]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
gh-140814: Fix freeze_support() setting start method as side effect (GH-144608)
authorGregory P. Smith <68491+gpshead@users.noreply.github.com>
Mon, 16 Mar 2026 05:50:19 +0000 (22:50 -0700)
committerGitHub <noreply@github.com>
Mon, 16 Mar 2026 05:50:19 +0000 (22:50 -0700)
freeze_support() called get_start_method() without allow_none=True,
which locked in the default start method context. This caused a
subsequent set_start_method() call to raise "context has already been
set". Use allow_none=True and accept None as a matching value, since
spawn.freeze_support() independently detects spawned child processes.

Test that freeze_support() does not lock in the default start method,
which would prevent a subsequent set_start_method() call.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-authored-by: Bénédikt Tran <10796600+picnixz@users.noreply.github.com>
Lib/multiprocessing/context.py
Lib/test/_test_multiprocessing.py
Misc/NEWS.d/next/Library/2026-02-08-22-04-06.gh-issue-140814.frzSpn.rst [new file with mode: 0644]

index a73261cde856bb709e58db99ccb867b1b76e3723..e1d251456024c075b4240b0d160a11033946c080 100644 (file)
@@ -145,7 +145,13 @@ class BaseContext(object):
         '''Check whether this is a fake forked process in a frozen executable.
         If so then run code specified by commandline and exit.
         '''
-        if self.get_start_method() == 'spawn' and getattr(sys, 'frozen', False):
+        # gh-140814: allow_none=True avoids locking in the default start
+        # method, which would cause a later set_start_method() to fail.
+        # None is safe to pass through: spawn.freeze_support()
+        # independently detects whether this process is a spawned
+        # child, so the start method check here is only an optimization.
+        if (getattr(sys, 'frozen', False)
+                and self.get_start_method(allow_none=True) in ('spawn', None)):
             from .spawn import freeze_support
             freeze_support()
 
index d67fd13fa33beda27684a42361b24df570eea6ea..490c7ae5e8076cdfbb38fe6e9d7bd075a45ad56f 100644 (file)
@@ -6005,6 +6005,20 @@ class TestStartMethod(unittest.TestCase):
             process.join()
             self.assertIsNone(multiprocessing.get_start_method(allow_none=True))
 
+    @only_run_in_spawn_testsuite("freeze_support is not start method specific")
+    def test_freeze_support_dont_set_context(self):
+        # gh-140814: freeze_support() should not set the start method
+        # as a side effect, so a later set_start_method() still works.
+        multiprocessing.set_start_method(None, force=True)
+        try:
+            multiprocessing.freeze_support()
+            self.assertIsNone(
+                multiprocessing.get_start_method(allow_none=True))
+            # Should not raise "context has already been set"
+            multiprocessing.set_start_method('spawn')
+        finally:
+            multiprocessing.set_start_method(None, force=True)
+
     def test_context_check_module_types(self):
         try:
             ctx = multiprocessing.get_context('forkserver')
diff --git a/Misc/NEWS.d/next/Library/2026-02-08-22-04-06.gh-issue-140814.frzSpn.rst b/Misc/NEWS.d/next/Library/2026-02-08-22-04-06.gh-issue-140814.frzSpn.rst
new file mode 100644 (file)
index 0000000..6077de8
--- /dev/null
@@ -0,0 +1,3 @@
+:func:`multiprocessing.freeze_support` no longer sets the default start method
+as a side effect, which previously caused a subsequent
+:func:`multiprocessing.set_start_method` call to raise :exc:`RuntimeError`.