Skip to content

Commit

Permalink
Clear potential ref cycle between Process and Process target (python#…
Browse files Browse the repository at this point in the history
…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
  • Loading branch information
pitrou authored and vstinner committed Jun 28, 2017
1 parent a79f8fa commit 79d37ae
Show file tree
Hide file tree
Showing 2 changed files with 21 additions and 0 deletions.
3 changes: 3 additions & 0 deletions Lib/multiprocessing/process.py
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,9 @@ def start(self):
_cleanup()
self._popen = self._Popen(self)
self._sentinel = self._popen.sentinel
# Avoid a refcycle if the target function holds an indirect
# reference to the process object (see bpo-30775)
del self._target, self._args, self._kwargs
_children.add(self)

def terminate(self):
Expand Down
18 changes: 18 additions & 0 deletions Lib/test/_test_multiprocessing.py
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,12 @@ def get_value(self):
# Testcases
#

class DummyCallable:
def __call__(self, q, c):
assert isinstance(c, DummyCallable)
q.put(5)


class _TestProcess(BaseTestCase):

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

def test_lose_target_ref(self):
c = DummyCallable()
wr = weakref.ref(c)
q = self.Queue()
p = self.Process(target=c, args=(q, c))
del c
p.start()
p.join()
self.assertIs(wr(), None)
self.assertEqual(q.get(), 5)


#
#
#
Expand Down

0 comments on commit 79d37ae

Please sign in to comment.