You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
In AutorecoveringModel, each time the QueueBind method is called, a new RecordedQueueBinding object is created and passed to the RecordBinding method of the AutorecoveringConnection class.
That RecordBinding method of the AutorecoveringConnection class expects a single parameter of type RecordedBinding, which RecordedQueueBinding extends, and that RecordedBinding is added to the protected m_recordedBindings variable that's declared as type HashSet<RecordedBinding>.
Ideally, a HashSet<T> ensures that it keeps no duplicate instances of T, and, if one looks at the change made in the commit of 2014-09-30 with SHA-1 of 5db2f44, one can see that the reason for using a HashSet for m_recordedBindings is, indeed, to ensure that no duplicate bindings are retained.
In that commit, in the AutorecoveringConnection class, the type for m_recordedBindings was changed from List<RecordedBinding> to HashSet<RecordedBinding>, and the RecordBinding method was changed from the following:
public void RecordBinding(RecordedBinding rb)
{
lock(this.m_recordedEntitiesLock)
{
// TODO: this operation is O(n)
if(!m_recordedBindings.Contains(rb))
{
m_recordedBindings.Add(rb);
}
}
}
to this:
public void RecordBinding(RecordedBinding rb)
{
lock(this.m_recordedEntitiesLock)
{
m_recordedBindings.Add(rb);
}
}
Notice that the check for whether or not the RecordedBinding is in the collection has been removed.
Why?
Because, again, using HashSet<RecordedBinding> should ensure that the collection contains no duplicates of RecordedBinding.
However, for that to be true, one must override both the GetHashCode() method and the Equals(object obj) method of RecordedBinding.cs
Unfortunately, while RecordedBinding had overridden the GetHashCode() method, the only custom Equals method defined had the following signature:
bool Equals(RecordedBinding other)
Thus, because the Equals(object obj) method was not overridden, every call to QueueBind has resulted in a new object being added to m_recordedBindings in AutorecoveringConnection, and when one needs to *guarantee* that the Queue binding is in place before publishing each message, with messages being published every second, one can see that this memory leak will cause problems quickly.
0 commit comments