PYTHON-799 Break ref cycle in Monitor.

Previous code to avoid the cycle was wrong.
This commit is contained in:
A. Jesse Jiryu Davis 2014-12-18 09:35:15 -05:00
parent 811864de88
commit 1ab83f72cf
2 changed files with 15 additions and 9 deletions

View File

@ -41,7 +41,7 @@ class Monitor(object):
"""
self._server_description = server_description
# A weakref callback, takes ref to the dead topology as its parameter.
# A weakref callback, takes ref to the freed topology as its parameter.
def close(dummy):
self.close()
@ -51,10 +51,15 @@ class Monitor(object):
self._avg_round_trip_time = MovingAverage()
# We strongly reference the executor and it weakly references us via
# this closure. When the monitor is freed, a call to target() raises
# ReferenceError and stops the executor.
# this closure. When the monitor is freed, stop the executor.
self_ref = weakref.ref(self)
def target():
Monitor._run(weakref.proxy(self))
monitor = self_ref()
if monitor is None:
return False # Stop the executor.
Monitor._run(monitor)
return True
self._executor = periodic_executor.PeriodicExecutor(
condition_class=self._settings.condition_class,

View File

@ -26,7 +26,7 @@ class PeriodicExecutor(object):
def __init__(self, condition_class, interval, min_interval, target):
""""Run a target function periodically on a background thread.
If the function raises an exception, the executor stops.
If the target's return value is false, the executor stops.
:Parameters:
- `condition_class`: A class like threading.Condition.
@ -84,11 +84,12 @@ class PeriodicExecutor(object):
def _run(self):
while not self._stopped:
try:
self._target()
except Exception:
# It's the target's responsibility to report errors.
if not self._target():
self._stopped = True
break
except:
self._stopped = True
break
raise
# Avoid running too frequently if wake() is called very often.
time.sleep(self._min_interval)