Skip to content

Commit 52820e2

Browse files
committed
audio: reland: bug fix: crash with uncomparable source
Closes #3039
1 parent 420a6c1 commit 52820e2

File tree

2 files changed

+42
-1
lines changed

2 files changed

+42
-1
lines changed

audio/audio.go

+13-1
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ import (
3737
"errors"
3838
"fmt"
3939
"io"
40+
"reflect"
4041
"runtime"
4142
"sync"
4243
"time"
@@ -188,11 +189,22 @@ func (c *Context) addPlayingPlayer(p *playerImpl) {
188189
defer c.m.Unlock()
189190
c.playingPlayers[p] = struct{}{}
190191

192+
// (reflect.Type).Comparable() is enough here, as reflect.TypeOf should always return a dynamic (non-interface) type.
193+
// If reflect.TypeOf returned an interface type, this check would be meaningless.
194+
// See these for more details:
195+
// * https://pkg.go.dev/reflect#TypeOf
196+
// * https://pkg.go.dev/reflect#Type.Comparable
197+
//
198+
// (*reflect.Value).Comparable() is more intuitive but this was introduced in Go 1.20.
199+
if !reflect.TypeOf(p.sourceIdent()).Comparable() {
200+
return
201+
}
202+
191203
// Check the source duplication
192204
srcs := map[any]struct{}{}
193205
for p := range c.playingPlayers {
194206
if _, ok := srcs[p.sourceIdent()]; ok {
195-
c.err = errors.New("audio: a same source is used by multiple Player")
207+
c.err = errors.New("audio: the same source must not be used by multiple Player objects")
196208
return
197209
}
198210
srcs[p.sourceIdent()] = struct{}{}

audio/audio_test.go

+29
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ package audio_test
1616

1717
import (
1818
"bytes"
19+
"io"
1920
"os"
2021
"runtime"
2122
"testing"
@@ -147,4 +148,32 @@ func TestNonSeekableSource(t *testing.T) {
147148

148149
p.Play()
149150
p.Pause()
151+
152+
if err := audio.UpdateForTesting(); err != nil {
153+
t.Error(err)
154+
}
155+
}
156+
157+
type uncomparableSource []int
158+
159+
func (uncomparableSource) Read(buf []byte) (int, error) {
160+
return 0, io.EOF
161+
}
162+
163+
// Issue #3039
164+
func TestUncomparableSource(t *testing.T) {
165+
setup()
166+
defer teardown()
167+
168+
p, err := context.NewPlayer(uncomparableSource{})
169+
if err != nil {
170+
t.Fatal(err)
171+
}
172+
173+
p.Play()
174+
p.Pause()
175+
176+
if err := audio.UpdateForTesting(); err != nil {
177+
t.Error(err)
178+
}
150179
}

0 commit comments

Comments
 (0)