diff --git a/server/channels/app/platform/web_hub.go b/server/channels/app/platform/web_hub.go index d37f3d4762..02652adf58 100644 --- a/server/channels/app/platform/web_hub.go +++ b/server/channels/app/platform/web_hub.go @@ -599,6 +599,8 @@ func (i *hubConnectionIndex) Remove(wc *WebConn) { last := userConnections[len(userConnections)-1] // set the slot that we are trying to remove to be the last connection. userConnections[userConnIndex] = last + // remove the last connection pointer from slice. + userConnections[len(userConnections)-1] = nil // remove the last connection from the slice. i.byUserId[wc.UserId] = userConnections[:len(userConnections)-1] // set the index of the connection that was moved to the new index. diff --git a/server/channels/app/platform/web_hub_test.go b/server/channels/app/platform/web_hub_test.go index 10db2fcb7c..0fc45e730c 100644 --- a/server/channels/app/platform/web_hub_test.go +++ b/server/channels/app/platform/web_hub_test.go @@ -8,6 +8,7 @@ import ( "net" "net/http" "net/http/httptest" + "runtime" "testing" "time" @@ -539,6 +540,42 @@ func BenchmarkHubConnIndex(b *testing.B) { }) } +func TestHubConnIndexRemoveMemLeak(t *testing.T) { + th := Setup(t) + defer th.TearDown() + + connIndex := newHubConnectionIndex(1 * time.Second) + + wc := &WebConn{ + Platform: th.Service, + Suite: th.Suite, + } + wc.SetConnectionID(model.NewId()) + wc.SetSession(&model.Session{}) + + ch := make(chan struct{}) + + runtime.SetFinalizer(wc, func(*WebConn) { + close(ch) + }) + + connIndex.Add(wc) + connIndex.Remove(wc) + + runtime.GC() + + timer := time.NewTimer(3 * time.Second) + defer timer.Stop() + + select { + case <-ch: + case <-timer.C: + require.Fail(t, "timeout waiting for collection of wc") + } + + assert.Len(t, connIndex.byConnection, 0) +} + var hubSink *Hub func BenchmarkGetHubForUserId(b *testing.B) {