diff --git a/cassandra/cluster.py b/cassandra/cluster.py index 468a0030..b2294017 100644 --- a/cassandra/cluster.py +++ b/cassandra/cluster.py @@ -478,6 +478,9 @@ class Cluster(object): self.sockopts = sockopts self.max_schema_agreement_wait = max_schema_agreement_wait + # let Session objects be GC'ed (and shutdown) when the user no longer + # holds a reference. Normally the cycle detector would handle this, + # but implementing __del__ prevents that. self.sessions = weakref.WeakSet() self.metadata = Metadata(self) self.control_connection = None @@ -697,6 +700,8 @@ class ControlConnection(object): _time = time def __init__(self, cluster): + # use a weak reference to allow the Cluster instance to be GC'ed (and + # shutdown) since implementing __del__ disables the cycle detector self._cluster = weakref.proxy(cluster) self._balancing_policy = RoundRobinPolicy() self._balancing_policy.populate(cluster, cluster.metadata.all_hosts()) diff --git a/cassandra/metadata.py b/cassandra/metadata.py index bb00751a..798193a6 100644 --- a/cassandra/metadata.py +++ b/cassandra/metadata.py @@ -34,6 +34,9 @@ unreserved_keywords = set(( class Metadata(object): def __init__(self, cluster): + # use a weak reference so that the Cluster object can be GC'ed. + # Normally the cycle detector would handle this, but implementing + # __del__ disables that. self.cluster_ref = weakref.ref(cluster) self.cluster_name = None self.keyspaces = {} diff --git a/cassandra/pool.py b/cassandra/pool.py index 22d9de60..c4b95f91 100644 --- a/cassandra/pool.py +++ b/cassandra/pool.py @@ -173,6 +173,9 @@ class HealthMonitor(object): def __init__(self, conviction_policy): self._conviction_policy = conviction_policy self._host = conviction_policy.host + # self._listeners will hold, among other things, references to + # Cluster objects. To allow those to be GC'ed (and shutdown) even + # though we've implemented __del__, use weak references. self._listeners = weakref.WeakSet() self._lock = RLock()