https://github.com/python/cpython/commit/20704014112b41b245373aba7dfc070c209c1678
commit: 20704014112b41b245373aba7dfc070c209c1678
branch: 3.13
author: Miss Islington (bot) <[email protected]>
committer: gpshead <[email protected]>
date: 2026-03-16T06:13:21Z
summary:

[3.13] gh-140814: Fix freeze_support() setting start method as side effect 
(GH-144608) (#146009)

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 <[email protected]>
Co-authored-by: Claude Opus 4.6 <[email protected]>
Co-authored-by: Bénédikt Tran <[email protected]>

files:
A Misc/NEWS.d/next/Library/2026-02-08-22-04-06.gh-issue-140814.frzSpn.rst
M Lib/multiprocessing/context.py
M Lib/test/_test_multiprocessing.py

diff --git a/Lib/multiprocessing/context.py b/Lib/multiprocessing/context.py
index f395e8b04d0cc1..07c8a5d1e2dd37 100644
--- a/Lib/multiprocessing/context.py
+++ b/Lib/multiprocessing/context.py
@@ -145,7 +145,13 @@ def freeze_support(self):
         '''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()
 
diff --git a/Lib/test/_test_multiprocessing.py 
b/Lib/test/_test_multiprocessing.py
index ded7c5249e155c..394ddcf44f92a7 100644
--- a/Lib/test/_test_multiprocessing.py
+++ b/Lib/test/_test_multiprocessing.py
@@ -5707,6 +5707,20 @@ def test_spawn_dont_set_context(self):
             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
index 00000000000000..6077de8ac9ae51
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2026-02-08-22-04-06.gh-issue-140814.frzSpn.rst
@@ -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`.

_______________________________________________
Python-checkins mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3//lists/python-checkins.python.org
Member address: [email protected]

Reply via email to