Cleanup statsGetter after peer is closed

This commit is contained in:
Joe Turki
2025-09-19 05:42:41 +03:00
parent 4c1261ff83
commit 9acbc661f6
3 changed files with 31 additions and 0 deletions

View File

@@ -69,6 +69,11 @@ func lookupStats(id string) (stats.Getter, bool) {
return nil, false return nil, false
} }
// cleanupStats removes the stats getter for a given peerconnection.statsId.
func cleanupStats(id string) {
statsGetter.Delete(id)
}
// key: string (peerconnection.statsId), value: stats.Getter // key: string (peerconnection.statsId), value: stats.Getter
var statsGetter sync.Map // nolint:gochecknoglobals var statsGetter sync.Map // nolint:gochecknoglobals

View File

@@ -384,6 +384,29 @@ func TestStatsInterceptorIsAddedByDefault(t *testing.T) {
) )
} }
// TestStatsGetterCleanup tests that statsGetter is properly cleaned up to prevent memory leaks.
func TestStatsGetterCleanup(t *testing.T) {
api := NewAPI()
pc, err := api.NewPeerConnection(Configuration{})
assert.NoError(t, err)
assert.NotNil(t, pc.statsGetter, "statsGetter should be non-nil after creation")
statsID := pc.statsID
getter, exists := lookupStats(statsID)
assert.True(t, exists, "global statsGetter map should contain entry for this PC")
assert.NotNil(t, getter, "looked up getter should not be nil")
assert.Equal(t, pc.statsGetter, getter, "field and global map getter should match")
assert.NoError(t, pc.Close())
assert.Nil(t, pc.statsGetter, "statsGetter field should be nil after close")
getter, exists = lookupStats(statsID)
assert.False(t, exists, "global statsGetter map should not contain entry after close")
assert.Nil(t, getter, "looked up getter should be nil after close")
}
// TestInterceptorNack is an end-to-end test for the NACK sender. // TestInterceptorNack is an end-to-end test for the NACK sender.
// It tests that: // It tests that:
// - we get a NACK if we negotiated generic NACks; // - we get a NACK if we negotiated generic NACks;

View File

@@ -2481,6 +2481,9 @@ func (pc *PeerConnection) close(shouldGracefullyClose bool) error { //nolint:cyc
closeErrs = append(closeErrs, doGracefulCloseOps()...) //nolint:makezero // todo fix closeErrs = append(closeErrs, doGracefulCloseOps()...) //nolint:makezero // todo fix
pc.statsGetter = nil
cleanupStats(pc.statsID)
// Interceptor closes at the end to prevent Bind from being called after interceptor is closed // Interceptor closes at the end to prevent Bind from being called after interceptor is closed
closeErrs = append(closeErrs, pc.api.interceptor.Close()) //nolint:makezero // todo fix closeErrs = append(closeErrs, pc.api.interceptor.Close()) //nolint:makezero // todo fix