diff options
-rw-r--r-- | Lib/test/test_threading.py | 20 | ||||
-rw-r--r-- | Lib/threading.py | 3 |
2 files changed, 23 insertions, 0 deletions
diff --git a/Lib/test/test_threading.py b/Lib/test/test_threading.py index 4f49d7f1cb..91f5a8b2df 100644 --- a/Lib/test/test_threading.py +++ b/Lib/test/test_threading.py @@ -8,6 +8,7 @@ import threading import thread import time import unittest +import weakref # A trivial mutable counter. class Counter(object): @@ -253,6 +254,25 @@ class ThreadTests(unittest.TestCase): finally: sys.setcheckinterval(old_interval) + def test_no_refcycle_through_target(self): + class RunSelfFunction(object): + def __init__(self): + # The links in this refcycle from Thread back to self + # should be cleaned up when the thread completes. + self.thread = threading.Thread(target=self._run, + args=(self,), + kwargs={'yet_another':self}) + self.thread.start() + + def _run(self, other_ref, yet_another): + pass + + cyclic_object = RunSelfFunction() + weak_cyclic_object = weakref.ref(cyclic_object) + cyclic_object.thread.join() + del cyclic_object + self.assertEquals(None, weak_cyclic_object()) + class ThreadingExceptionTests(unittest.TestCase): # A RuntimeError should be raised if Thread.start() is called diff --git a/Lib/threading.py b/Lib/threading.py index 409360dae2..2f472b47aa 100644 --- a/Lib/threading.py +++ b/Lib/threading.py @@ -444,6 +444,9 @@ class Thread(_Verbose): def run(self): if self.__target: self.__target(*self.__args, **self.__kwargs) + # Avoid a refcycle if the thread is running a function with an + # argument that has a member that points to the thread. + del self.__target, self.__args, self.__kwargs def __bootstrap(self): # Wrapper around the real bootstrap code that ignores |