]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
[3.14] gh-138813: Fix mutable default kwargs={} in multiprocessing BaseProcess and...
authorMiss Islington (bot) <31488909+miss-islington@users.noreply.github.com>
Wed, 8 Oct 2025 00:37:30 +0000 (02:37 +0200)
committerGitHub <noreply@github.com>
Wed, 8 Oct 2025 00:37:30 +0000 (00:37 +0000)
gh-138813: Fix mutable default kwargs={} in multiprocessing BaseProcess and DummyProcess to use None (GH-138814)

* gh-138813: Default `BaseProcess` `kwargs` to `None` (GH-138814)

Set `BaseProcess.__init__(..., kwargs=None)` and initialize `kwargs` with
`dict(kwargs) if kwargs else {}`. This avoids a shared mutable default and
matches threading.Thread behavior.

* DummyProcess kwargs=None (which threading.Thread accepts properly)
(cherry picked from commit 5a15e7378996358848394930343e9633b6fec8a9)

Co-authored-by: Denis Sergeev <newjimbatler00@gmail.com>
Co-authored-by: Gregory P. Smith <greg@krypto.org>
Co-authored-by: Petr Viktorin <encukou@gmail.com>
Co-authored-by: Gregory P. Smith <68491+gpshead@users.noreply.github.com>
Lib/multiprocessing/dummy/__init__.py
Lib/multiprocessing/process.py
Lib/test/_test_multiprocessing.py
Misc/NEWS.d/next/Library/2025-09-17-08-32-43.gh-issue-138813.LHkHjX.rst [new file with mode: 0644]

index 6a1468609e347b3a0b9281e5c9e6ec311fcb37e5..7dc5d1c8dde8484e59728eb6dfa7a36c158dd2ef 100644 (file)
@@ -33,7 +33,7 @@ from queue import Queue
 
 class DummyProcess(threading.Thread):
 
-    def __init__(self, group=None, target=None, name=None, args=(), kwargs={}):
+    def __init__(self, group=None, target=None, name=None, args=(), kwargs=None):
         threading.Thread.__init__(self, group, target, name, args, kwargs)
         self._pid = None
         self._children = weakref.WeakKeyDictionary()
index 9db322be1aa6d6346fde20878d60889bd9c4fd90..262513f295fde56f2a0ca763e15ab4fb43d68424 100644 (file)
@@ -77,7 +77,7 @@ class BaseProcess(object):
     def _Popen(self):
         raise NotImplementedError
 
-    def __init__(self, group=None, target=None, name=None, args=(), kwargs={},
+    def __init__(self, group=None, target=None, name=None, args=(), kwargs=None,
                  *, daemon=None):
         assert group is None, 'group argument must be None for now'
         count = next(_process_counter)
@@ -89,7 +89,7 @@ class BaseProcess(object):
         self._closed = False
         self._target = target
         self._args = tuple(args)
-        self._kwargs = dict(kwargs)
+        self._kwargs = dict(kwargs) if kwargs else {}
         self._name = name or type(self).__name__ + '-' + \
                      ':'.join(str(i) for i in self._identity)
         if daemon is not None:
index a7fa862d4cf1006f998f041ab23f9f20f3caa21e..047d17aed41d50686ae896e3fab732a20685c367 100644 (file)
@@ -5173,6 +5173,23 @@ class TestInvalidHandle(unittest.TestCase):
                           multiprocessing.connection.Connection, -1)
 
 
+#
+# Regression tests for BaseProcess kwargs handling
+#
+
+class TestBaseProcessKwargs(unittest.TestCase):
+    def test_default_kwargs_not_shared_between_instances(self):
+        # Creating multiple Process instances without passing kwargs
+        # must create independent empty dicts (no shared state).
+        p1 = multiprocessing.Process(target=lambda: None)
+        p2 = multiprocessing.Process(target=lambda: None)
+        self.assertIsInstance(p1._kwargs, dict)
+        self.assertIsInstance(p2._kwargs, dict)
+        self.assertIsNot(p1._kwargs, p2._kwargs)
+        # Mutating one should not affect the other
+        p1._kwargs['x'] = 1
+        self.assertNotIn('x', p2._kwargs)
+
 
 @hashlib_helper.requires_hashdigest('sha256')
 class OtherTest(unittest.TestCase):
diff --git a/Misc/NEWS.d/next/Library/2025-09-17-08-32-43.gh-issue-138813.LHkHjX.rst b/Misc/NEWS.d/next/Library/2025-09-17-08-32-43.gh-issue-138813.LHkHjX.rst
new file mode 100644 (file)
index 0000000..97f4d76
--- /dev/null
@@ -0,0 +1 @@
+:class:`!multiprocessing.BaseProcess` defaults ``kwargs`` to ``None`` instead of a shared dictionary.