]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
[3.13] gh-140814: Fix freeze_support() setting start method as side effect (GH-144608...
authorMiss Islington (bot) <31488909+miss-islington@users.noreply.github.com>
Mon, 16 Mar 2026 06:13:21 +0000 (07:13 +0100)
committerGitHub <noreply@github.com>
Mon, 16 Mar 2026 06:13:21 +0000 (06:13 +0000)
gh-140814: Fix freeze_support() setting start method as side effect (GH-144608)

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.
(cherry picked from commit ee5318025b0f9f4d30d9358627df68181e0d223f)

Co-authored-by: Gregory P. Smith <68491+gpshead@users.noreply.github.com>
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 f395e8b04d0cc1760e6462640ada7d0957df36bc..07c8a5d1e2dd37532d0e77388cd295bfd7446090 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 ded7c5249e155c3d8863a2f7f659261e5604bdfe..394ddcf44f92a753fc72a30ae6fd36de7bfe8cdb 100644 (file)
@@ -5707,6 +5707,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`.