Skip to content

Commit 12536bd

Browse files
pitrouvstinner
authored andcommitted
[2.7] Clear potential ref cycle between Process and Process target (GH-2470) (#2473)
* 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. (cherry picked from commit 79d37ae)
1 parent 5b5002c commit 12536bd

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
@@ -128,6 +128,9 @@ def start(self):
128128
else:
129129
from .forking import Popen
130130
self._popen = Popen(self)
131+
# Avoid a refcycle if the target function holds an indirect
132+
# reference to the process object (see bpo-30775)
133+
del self._target, self._args, self._kwargs
131134
_current_process._children.add(self)
132135

133136
def terminate(self):

Lib/test/test_multiprocessing.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,12 @@ def get_value(self):
175175
# Testcases
176176
#
177177

178+
class DummyCallable(object):
179+
def __call__(self, q, c):
180+
assert isinstance(c, DummyCallable)
181+
q.put(5)
182+
183+
178184
class _TestProcess(BaseTestCase):
179185

180186
ALLOWED_TYPES = ('processes', 'threads')
@@ -355,6 +361,18 @@ def test_sys_exit(self):
355361
p.join(5)
356362
self.assertEqual(p.exitcode, reason)
357363

364+
def test_lose_target_ref(self):
365+
c = DummyCallable()
366+
wr = weakref.ref(c)
367+
q = self.Queue()
368+
p = self.Process(target=c, args=(q, c))
369+
del c
370+
p.start()
371+
p.join()
372+
self.assertIs(wr(), None)
373+
self.assertEqual(q.get(), 5)
374+
375+
358376
#
359377
#
360378
#

0 commit comments

Comments
 (0)