Skip to content

Commit

Permalink
Avoid leaking tickers
Browse files Browse the repository at this point in the history
In Go 1.22 and earlier, a ticker needs to be explicitly stopped
when it's no longer useful in order to avoid a resource leak.
In Go 1.23 and later, an orphaned ticker will eventually be
garbage collected, but it's still more thrifty to stop it early.
  • Loading branch information
jech authored and Sean-Der committed Aug 1, 2024
1 parent cbbb1c2 commit f29ef99
Show file tree
Hide file tree
Showing 15 changed files with 34 additions and 9 deletions.
1 change: 1 addition & 0 deletions examples/bandwidth-estimation-from-disk/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -194,6 +194,7 @@ func main() {
// * avoids accumulating skew, just calling time.Sleep didn't compensate for the time spent parsing the data
// * works around latency issues with Sleep (see https://github.com/golang/go/issues/44343)
ticker := time.NewTicker(time.Millisecond * time.Duration((float32(header.TimebaseNumerator)/float32(header.TimebaseDenominator))*1000))
defer ticker.Stop()
frame := []byte{}
frameHeader := &ivfreader.IVFFrameHeader{}
currentTimestamp := uint64(0)
Expand Down
4 changes: 3 additions & 1 deletion examples/data-channels-detach/jsfiddle/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,9 @@ func ReadLoop(d io.Reader) {

// WriteLoop shows how to write to the datachannel directly
func WriteLoop(d io.Writer) {
for range time.NewTicker(5 * time.Second).C {
ticker := time.NewTicker(5 * time.Second)
defer ticker.Stop()
for range ticker.C {
message, err := randutil.GenerateCryptoRandomString(messageSize, "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ")
if err != nil {
handleError(err)
Expand Down
4 changes: 3 additions & 1 deletion examples/data-channels-detach/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,9 @@ func ReadLoop(d io.Reader) {

// WriteLoop shows how to write to the datachannel directly
func WriteLoop(d io.Writer) {
for range time.NewTicker(5 * time.Second).C {
ticker := time.NewTicker(5 * time.Second)
defer ticker.Stop()
for range ticker.C {
message, err := randutil.GenerateCryptoRandomString(messageSize, "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ")
if err != nil {
panic(err)
Expand Down
4 changes: 3 additions & 1 deletion examples/data-channels-flow-control/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,9 @@ func createAnswerer() *webrtc.PeerConnection {
since := time.Now()

// Start printing out the observed throughput
for range time.NewTicker(1000 * time.Millisecond).C {
ticker := time.NewTicker(1000 * time.Millisecond)
defer ticker.Stop()
for range ticker.C {
bps := float64(atomic.LoadUint64(&totalBytesReceived)*8) / time.Since(since).Seconds()
log.Printf("Throughput: %.03f Mbps", bps/1024/1024)
}
Expand Down
4 changes: 3 additions & 1 deletion examples/data-channels/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,9 @@ func main() {
d.OnOpen(func() {
fmt.Printf("Data channel '%s'-'%d' open. Random messages will now be sent to any connected DataChannels every 5 seconds\n", d.Label(), d.ID())

for range time.NewTicker(5 * time.Second).C {
ticker := time.NewTicker(5 * time.Second)
defer ticker.Stop()
for range ticker.C {
message, sendErr := randutil.GenerateCryptoRandomString(15, "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ")
if sendErr != nil {
panic(sendErr)
Expand Down
3 changes: 2 additions & 1 deletion examples/insertable-streams/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,8 @@ func main() {
// * avoids accumulating skew, just calling time.Sleep didn't compensate for the time spent parsing the data
// * works around latency issues with Sleep (see https://github.com/golang/go/issues/44343)
ticker := time.NewTicker(time.Millisecond * time.Duration((float32(header.TimebaseNumerator)/float32(header.TimebaseDenominator))*1000))
for ; true; <-ticker.C {
defer ticker.Stop()
for range ticker.C {
frame, _, ivfErr := ivf.ParseNextFrame()
if errors.Is(ivfErr, io.EOF) {
fmt.Printf("All frames parsed and sent")
Expand Down
1 change: 1 addition & 0 deletions examples/ortc-media/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -223,6 +223,7 @@ func fourCCToTrack(fourCC string) *webrtc.TrackLocalStaticSample {
// Write a file to Track
func writeFileToTrack(ivf *ivfreader.IVFReader, header *ivfreader.IVFFileHeader, track *webrtc.TrackLocalStaticSample) {
ticker := time.NewTicker(time.Millisecond * time.Duration((float32(header.TimebaseNumerator)/float32(header.TimebaseDenominator))*1000))
defer ticker.Stop()
for ; true; <-ticker.C {
frame, _, err := ivf.ParseNextFrame()
if errors.Is(err, io.EOF) {
Expand Down
4 changes: 3 additions & 1 deletion examples/ortc/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -183,7 +183,9 @@ func handleOnOpen(channel *webrtc.DataChannel) func() {
return func() {
fmt.Printf("Data channel '%s'-'%d' open. Random messages will now be sent to any connected DataChannels every 5 seconds\n", channel.Label(), channel.ID())

for range time.NewTicker(5 * time.Second).C {
ticker := time.NewTicker(5 * time.Second)
defer ticker.Stop()
for range ticker.C {
message, err := randutil.GenerateCryptoRandomString(15, "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ")
if err != nil {
panic(err)
Expand Down
4 changes: 3 additions & 1 deletion examples/pion-to-pion/answer/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,9 @@ func main() { // nolint:gocognit
d.OnOpen(func() {
fmt.Printf("Data channel '%s'-'%d' open. Random messages will now be sent to any connected DataChannels every 5 seconds\n", d.Label(), d.ID())

for range time.NewTicker(5 * time.Second).C {
ticker := time.NewTicker(5 * time.Second)
defer ticker.Stop()
for range ticker.C {
message, sendTextErr := randutil.GenerateCryptoRandomString(15, "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ")
if sendTextErr != nil {
panic(sendTextErr)
Expand Down
4 changes: 3 additions & 1 deletion examples/pion-to-pion/offer/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,9 @@ func main() { //nolint:gocognit
dataChannel.OnOpen(func() {
fmt.Printf("Data channel '%s'-'%d' open. Random messages will now be sent to any connected DataChannels every 5 seconds\n", dataChannel.Label(), dataChannel.ID())

for range time.NewTicker(5 * time.Second).C {
ticker := time.NewTicker(5 * time.Second)
defer ticker.Stop()
for range ticker.C {
message, sendTextErr := randutil.GenerateCryptoRandomString(15, "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ")
if sendTextErr != nil {
panic(sendTextErr)
Expand Down
1 change: 1 addition & 0 deletions examples/play-from-disk-renegotiation/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,7 @@ func writeVideoToTrack(t *webrtc.TrackLocalStaticSample) {
// * avoids accumulating skew, just calling time.Sleep didn't compensate for the time spent parsing the data
// * works around latency issues with Sleep (see https://github.com/golang/go/issues/44343)
ticker := time.NewTicker(time.Millisecond * time.Duration((float32(header.TimebaseNumerator)/float32(header.TimebaseDenominator))*1000))
defer ticker.Stop()
for ; true; <-ticker.C {
frame, _, err := ivf.ParseNextFrame()
if err != nil {
Expand Down
2 changes: 2 additions & 0 deletions examples/play-from-disk/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,7 @@ func main() {
// * avoids accumulating skew, just calling time.Sleep didn't compensate for the time spent parsing the data
// * works around latency issues with Sleep (see https://github.com/golang/go/issues/44343)
ticker := time.NewTicker(time.Millisecond * time.Duration((float32(header.TimebaseNumerator)/float32(header.TimebaseDenominator))*1000))
defer ticker.Stop()
for ; true; <-ticker.C {
frame, _, ivfErr := ivf.ParseNextFrame()
if errors.Is(ivfErr, io.EOF) {
Expand Down Expand Up @@ -197,6 +198,7 @@ func main() {
// * avoids accumulating skew, just calling time.Sleep didn't compensate for the time spent parsing the data
// * works around latency issues with Sleep (see https://github.com/golang/go/issues/44343)
ticker := time.NewTicker(oggPageDuration)
defer ticker.Stop()
for ; true; <-ticker.C {
pageData, pageHeader, oggErr := ogg.ParseNextPage()
if errors.Is(oggErr, io.EOF) {
Expand Down
1 change: 1 addition & 0 deletions examples/simulcast/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,7 @@ func main() {
rid := track.RID()
go func() {
ticker := time.NewTicker(3 * time.Second)
defer ticker.Stop()
for range ticker.C {
fmt.Printf("Sending pli for stream with rid: %q, ssrc: %d\n", track.RID(), track.SSRC())
if writeErr := peerConnection.WriteRTCP([]rtcp.Packet{&rtcp.PictureLossIndication{MediaSSRC: uint32(track.SSRC())}}); writeErr != nil {
Expand Down
5 changes: 4 additions & 1 deletion interceptor_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@ func TestPeerConnection_Interceptor(t *testing.T) {

func() {
ticker := time.NewTicker(time.Millisecond * 20)
defer ticker.Stop()
for {
select {
case <-seenRTP.Done():
Expand Down Expand Up @@ -252,7 +253,9 @@ func Test_Interceptor_ZeroSSRC(t *testing.T) {

go func() {
sequenceNumber := uint16(0)
for range time.NewTicker(time.Millisecond * 20).C {
ticker := time.NewTicker(time.Millisecond * 20)
defer ticker.Stop()
for range ticker.C {
track.mu.Lock()
if len(track.bindings) == 1 {
_, err = track.bindings[0].writeStream.WriteRTP(&rtp.Header{
Expand Down
1 change: 1 addition & 0 deletions peerconnection_media_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1000,6 +1000,7 @@ func TestPeerConnection_Simulcast_Probe(t *testing.T) {
assert.NoError(t, err)

ticker := time.NewTicker(time.Millisecond * 20)
defer ticker.Stop()
testFinished := make(chan struct{})
seenFiveStreams, seenFiveStreamsCancel := context.WithCancel(context.Background())

Expand Down

0 comments on commit f29ef99

Please sign in to comment.