Skip to content

Commit d12daa5

Browse files
committed
Fix memory leak with nackcountlogs
1 parent 8dddb51 commit d12daa5

File tree

2 files changed

+51
-0
lines changed

2 files changed

+51
-0
lines changed

pkg/nack/generator_interceptor.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,8 @@ func (n *GeneratorInterceptor) BindRemoteStream(
124124
func (n *GeneratorInterceptor) UnbindRemoteStream(info *interceptor.StreamInfo) {
125125
n.receiveLogsMu.Lock()
126126
delete(n.receiveLogs, info.SSRC)
127+
// the count logs must also be dropped for the specific SSRC.
128+
delete(n.nackCountLogs, info.SSRC)
127129
n.receiveLogsMu.Unlock()
128130
}
129131

@@ -204,6 +206,11 @@ func (n *GeneratorInterceptor) loop(rtcpWriter interceptor.RTCPWriter) {
204206
}
205207
}
206208

209+
// clean up the count log for the ssrc if it's empty
210+
if len(n.nackCountLogs[ssrc]) == 0 {
211+
delete(n.nackCountLogs, ssrc)
212+
}
213+
207214
if _, err := rtcpWriter.Write([]rtcp.Packet{nack}, interceptor.Attributes{}); err != nil {
208215
n.log.Warnf("failed sending nack: %+v", err)
209216
}

pkg/nack/generator_interceptor_test.go

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,3 +135,47 @@ func TestGeneratorInterceptor_StreamFilter(t *testing.T) {
135135
}
136136
}
137137
}
138+
139+
func TestGeneratorInterceptor_UnbindRemovesCorrespondingSSRC(t *testing.T) {
140+
f, err := NewGeneratorInterceptor(
141+
GeneratorSize(64),
142+
)
143+
assert.NoError(t, err)
144+
145+
i, err := f.NewInterceptor("")
146+
assert.NoError(t, err)
147+
gen, ok := i.(*GeneratorInterceptor)
148+
assert.True(t, ok, "expected *GeneratorInterceptor, got %T", i)
149+
150+
const ssrc = uint32(1234)
151+
152+
info := &interceptor.StreamInfo{
153+
SSRC: ssrc,
154+
RTCPFeedback: []interceptor.RTCPFeedback{{Type: "nack"}},
155+
}
156+
157+
rl, err := newReceiveLog(gen.size)
158+
assert.NoError(t, err)
159+
160+
// make the receive log and count logs non-empty
161+
gen.receiveLogsMu.Lock()
162+
gen.receiveLogs[ssrc] = rl
163+
gen.nackCountLogs[ssrc] = map[uint16]uint16{
164+
10: 1,
165+
20: 2,
166+
}
167+
gen.receiveLogsMu.Unlock()
168+
169+
// unbind the stream
170+
gen.UnbindRemoteStream(info)
171+
172+
// compare them and ensure that ssrc isn't there
173+
gen.receiveLogsMu.Lock()
174+
defer gen.receiveLogsMu.Unlock()
175+
176+
_, ok = gen.receiveLogs[ssrc]
177+
assert.False(t, ok, "ssrc should not be present in receiveLogs")
178+
179+
_, ok = gen.nackCountLogs[ssrc]
180+
assert.False(t, ok, "ssrc should not be present in nackCountLogs")
181+
}

0 commit comments

Comments
 (0)