Skip to content

Commit 6b26e62

Browse files
miss-islingtonzeff-irgpsheadencukou
authored
[3.14] gh-138813: Fix mutable default kwargs={} in multiprocessing BaseProcess and DummyProcess to use None (GH-138814) (#139084)
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 5a15e73) Co-authored-by: Denis Sergeev <[email protected]> Co-authored-by: Gregory P. Smith <[email protected]> Co-authored-by: Petr Viktorin <[email protected]> Co-authored-by: Gregory P. Smith <[email protected]>
1 parent 64f0e2d commit 6b26e62

File tree

4 files changed

+21
-3
lines changed

4 files changed

+21
-3
lines changed

Lib/multiprocessing/dummy/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@
3333

3434
class DummyProcess(threading.Thread):
3535

36-
def __init__(self, group=None, target=None, name=None, args=(), kwargs={}):
36+
def __init__(self, group=None, target=None, name=None, args=(), kwargs=None):
3737
threading.Thread.__init__(self, group, target, name, args, kwargs)
3838
self._pid = None
3939
self._children = weakref.WeakKeyDictionary()

Lib/multiprocessing/process.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ class BaseProcess(object):
7777
def _Popen(self):
7878
raise NotImplementedError
7979

80-
def __init__(self, group=None, target=None, name=None, args=(), kwargs={},
80+
def __init__(self, group=None, target=None, name=None, args=(), kwargs=None,
8181
*, daemon=None):
8282
assert group is None, 'group argument must be None for now'
8383
count = next(_process_counter)
@@ -89,7 +89,7 @@ def __init__(self, group=None, target=None, name=None, args=(), kwargs={},
8989
self._closed = False
9090
self._target = target
9191
self._args = tuple(args)
92-
self._kwargs = dict(kwargs)
92+
self._kwargs = dict(kwargs) if kwargs else {}
9393
self._name = name or type(self).__name__ + '-' + \
9494
':'.join(str(i) for i in self._identity)
9595
if daemon is not None:

Lib/test/_test_multiprocessing.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5173,6 +5173,23 @@ def test_invalid_handles(self):
51735173
multiprocessing.connection.Connection, -1)
51745174

51755175

5176+
#
5177+
# Regression tests for BaseProcess kwargs handling
5178+
#
5179+
5180+
class TestBaseProcessKwargs(unittest.TestCase):
5181+
def test_default_kwargs_not_shared_between_instances(self):
5182+
# Creating multiple Process instances without passing kwargs
5183+
# must create independent empty dicts (no shared state).
5184+
p1 = multiprocessing.Process(target=lambda: None)
5185+
p2 = multiprocessing.Process(target=lambda: None)
5186+
self.assertIsInstance(p1._kwargs, dict)
5187+
self.assertIsInstance(p2._kwargs, dict)
5188+
self.assertIsNot(p1._kwargs, p2._kwargs)
5189+
# Mutating one should not affect the other
5190+
p1._kwargs['x'] = 1
5191+
self.assertNotIn('x', p2._kwargs)
5192+
51765193

51775194
@hashlib_helper.requires_hashdigest('sha256')
51785195
class OtherTest(unittest.TestCase):
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
:class:`!multiprocessing.BaseProcess` defaults ``kwargs`` to ``None`` instead of a shared dictionary.

0 commit comments

Comments
 (0)