mirror of
https://github.com/python/cpython.git
synced 2025-07-29 06:05:00 +00:00
Followup to r61011: Also avoid the reference cycle when the Thread's target
raises an exception.
This commit is contained in:
parent
3414ea9ed9
commit
a885c1521a
2 changed files with 18 additions and 8 deletions
|
@ -256,23 +256,31 @@ class ThreadTests(unittest.TestCase):
|
||||||
|
|
||||||
def test_no_refcycle_through_target(self):
|
def test_no_refcycle_through_target(self):
|
||||||
class RunSelfFunction(object):
|
class RunSelfFunction(object):
|
||||||
def __init__(self):
|
def __init__(self, should_raise):
|
||||||
# The links in this refcycle from Thread back to self
|
# The links in this refcycle from Thread back to self
|
||||||
# should be cleaned up when the thread completes.
|
# should be cleaned up when the thread completes.
|
||||||
|
self.should_raise = should_raise
|
||||||
self.thread = threading.Thread(target=self._run,
|
self.thread = threading.Thread(target=self._run,
|
||||||
args=(self,),
|
args=(self,),
|
||||||
kwargs={'yet_another':self})
|
kwargs={'yet_another':self})
|
||||||
self.thread.start()
|
self.thread.start()
|
||||||
|
|
||||||
def _run(self, other_ref, yet_another):
|
def _run(self, other_ref, yet_another):
|
||||||
pass
|
if self.should_raise:
|
||||||
|
raise SystemExit
|
||||||
|
|
||||||
cyclic_object = RunSelfFunction()
|
cyclic_object = RunSelfFunction(should_raise=False)
|
||||||
weak_cyclic_object = weakref.ref(cyclic_object)
|
weak_cyclic_object = weakref.ref(cyclic_object)
|
||||||
cyclic_object.thread.join()
|
cyclic_object.thread.join()
|
||||||
del cyclic_object
|
del cyclic_object
|
||||||
self.assertEquals(None, weak_cyclic_object())
|
self.assertEquals(None, weak_cyclic_object())
|
||||||
|
|
||||||
|
raising_cyclic_object = RunSelfFunction(should_raise=True)
|
||||||
|
weak_raising_cyclic_object = weakref.ref(raising_cyclic_object)
|
||||||
|
raising_cyclic_object.thread.join()
|
||||||
|
del raising_cyclic_object
|
||||||
|
self.assertEquals(None, weak_raising_cyclic_object())
|
||||||
|
|
||||||
|
|
||||||
class ThreadingExceptionTests(unittest.TestCase):
|
class ThreadingExceptionTests(unittest.TestCase):
|
||||||
# A RuntimeError should be raised if Thread.start() is called
|
# A RuntimeError should be raised if Thread.start() is called
|
||||||
|
|
|
@ -442,10 +442,12 @@ class Thread(_Verbose):
|
||||||
_sleep(0.000001) # 1 usec, to let the thread run (Solaris hack)
|
_sleep(0.000001) # 1 usec, to let the thread run (Solaris hack)
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
|
try:
|
||||||
if self.__target:
|
if self.__target:
|
||||||
self.__target(*self.__args, **self.__kwargs)
|
self.__target(*self.__args, **self.__kwargs)
|
||||||
# Avoid a refcycle if the thread is running a function with an
|
finally:
|
||||||
# argument that has a member that points to the thread.
|
# 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
|
del self.__target, self.__args, self.__kwargs
|
||||||
|
|
||||||
def __bootstrap(self):
|
def __bootstrap(self):
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue