Skip to content

Commit 79d37ae

Browse files
pitrouvstinner
authored andcommitted
Clear potential ref cycle between Process and Process target (#2470)
* Clear potential ref cycle between Process and Process target Besides Process.join() not being called, this was an indirect cause of bpo-30775. The threading module already does this. * Add issue reference
1 parent a79f8fa commit 79d37ae

File tree

2 files changed

+21
-0
lines changed

2 files changed

+21
-0
lines changed

Lib/multiprocessing/process.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,9 @@ def start(self):
110110
_cleanup()
111111
self._popen = self._Popen(self)
112112
self._sentinel = self._popen.sentinel
113+
# Avoid a refcycle if the target function holds an indirect
114+
# reference to the process object (see bpo-30775)
115+
del self._target, self._args, self._kwargs
113116
_children.add(self)
114117

115118
def terminate(self):

Lib/test/_test_multiprocessing.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -191,6 +191,12 @@ def get_value(self):
191191
# Testcases
192192
#
193193

194+
class DummyCallable:
195+
def __call__(self, q, c):
196+
assert isinstance(c, DummyCallable)
197+
q.put(5)
198+
199+
194200
class _TestProcess(BaseTestCase):
195201

196202
ALLOWED_TYPES = ('processes', 'threads')
@@ -469,6 +475,18 @@ def test_many_processes(self):
469475
for p in procs:
470476
self.assertEqual(p.exitcode, -signal.SIGTERM)
471477

478+
def test_lose_target_ref(self):
479+
c = DummyCallable()
480+
wr = weakref.ref(c)
481+
q = self.Queue()
482+
p = self.Process(target=c, args=(q, c))
483+
del c
484+
p.start()
485+
p.join()
486+
self.assertIs(wr(), None)
487+
self.assertEqual(q.get(), 5)
488+
489+
472490
#
473491
#
474492
#

0 commit comments

Comments
 (0)