From 3d383d700e6d2528a0864751b40527b41139a95c Mon Sep 17 00:00:00 2001 From: AN Long Date: Sun, 22 Jun 2025 15:45:30 +0900 Subject: [PATCH 1/3] multiprocessing.freeze_support no longer sets the start method globally. --- Lib/multiprocessing/context.py | 11 +++++++++++ .../2025-06-22-15-42-10.gh-issue-135726._oO5IN.rst | 2 ++ 2 files changed, 13 insertions(+) create mode 100644 Misc/NEWS.d/next/Library/2025-06-22-15-42-10.gh-issue-135726._oO5IN.rst diff --git a/Lib/multiprocessing/context.py b/Lib/multiprocessing/context.py index 051d567d457928..1bbbb9e78001ca 100644 --- a/Lib/multiprocessing/context.py +++ b/Lib/multiprocessing/context.py @@ -266,6 +266,17 @@ def get_all_start_methods(self): ) return start_method_names + 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. + ''' + start_method = self.get_start_method(allow_none=True) + if start_method is None: + start_method = self._default_context.get_start_method() + if start_method == 'spawn' and getattr(sys, 'frozen', False): + from .spawn import freeze_support + freeze_support() + # # Context types for fixed start method diff --git a/Misc/NEWS.d/next/Library/2025-06-22-15-42-10.gh-issue-135726._oO5IN.rst b/Misc/NEWS.d/next/Library/2025-06-22-15-42-10.gh-issue-135726._oO5IN.rst new file mode 100644 index 00000000000000..ef8070988683a2 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2025-06-22-15-42-10.gh-issue-135726._oO5IN.rst @@ -0,0 +1,2 @@ +:func:`multiprocessing.freeze_support` no longer sets the start method +globally. From d566cf69a1141833902007b88d121eb252cad5cc Mon Sep 17 00:00:00 2001 From: AN Long Date: Thu, 26 Jun 2025 23:55:15 +0900 Subject: [PATCH 2/3] Update BaseContext.freeze_support instead of override it --- Lib/multiprocessing/context.py | 26 ++++++++++++-------------- Lib/test/_test_multiprocessing.py | 7 +++++++ 2 files changed, 19 insertions(+), 14 deletions(-) diff --git a/Lib/multiprocessing/context.py b/Lib/multiprocessing/context.py index 1bbbb9e78001ca..d8aae721fa0645 100644 --- a/Lib/multiprocessing/context.py +++ b/Lib/multiprocessing/context.py @@ -145,9 +145,18 @@ 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): - from .spawn import freeze_support - freeze_support() + if not getattr(sys, 'frozen', False): + return + + # GH-135726: allow_none=True prevents this "get" call from setting the + # default context as the selected one as a side-effect. + method = self.get_start_method(allow_none=True) \ + or _default_context.get_start_method(allow_none=True) + if method != "spawn": + return + + from .spawn import freeze_support + freeze_support() def get_logger(self): '''Return package logger -- if it does not already exist then @@ -266,17 +275,6 @@ def get_all_start_methods(self): ) return start_method_names - 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. - ''' - start_method = self.get_start_method(allow_none=True) - if start_method is None: - start_method = self._default_context.get_start_method() - if start_method == 'spawn' and getattr(sys, 'frozen', False): - from .spawn import freeze_support - freeze_support() - # # Context types for fixed start method diff --git a/Lib/test/_test_multiprocessing.py b/Lib/test/_test_multiprocessing.py index a1259ff1d63d18..7a83bada093c70 100644 --- a/Lib/test/_test_multiprocessing.py +++ b/Lib/test/_test_multiprocessing.py @@ -5823,6 +5823,13 @@ def test_context(self): self.assertRaises(ValueError, ctx.set_start_method, None) self.check_context(ctx) + def test_freeze_support_side_effect(self): + # GH-135726: freeze_support() should not set the start method + # as a side-feect, + multiprocessing.set_start_method(None, force=True) + multiprocessing.freeze_support() + self.assertIsNone(multiprocessing.get_start_method(allow_none=True)) + def test_context_check_module_types(self): try: ctx = multiprocessing.get_context('forkserver') From 93ae860427e42d7351bffa35b2e0bf89c4544173 Mon Sep 17 00:00:00 2001 From: AN Long Date: Wed, 3 Sep 2025 21:53:19 +0900 Subject: [PATCH 3/3] Update Lib/multiprocessing/context.py Co-authored-by: Serhiy Storchaka --- Lib/multiprocessing/context.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Lib/multiprocessing/context.py b/Lib/multiprocessing/context.py index d8aae721fa0645..00bb89a67f1392 100644 --- a/Lib/multiprocessing/context.py +++ b/Lib/multiprocessing/context.py @@ -150,8 +150,8 @@ def freeze_support(self): # GH-135726: allow_none=True prevents this "get" call from setting the # default context as the selected one as a side-effect. - method = self.get_start_method(allow_none=True) \ - or _default_context.get_start_method(allow_none=True) + method = (self.get_start_method(allow_none=True) + or _default_context.get_start_method(allow_none=True)) if method != "spawn": return