Skip to content

Commit b1d8c7c

Browse files
committed
internal/mux: bug fix: race condition on the temporary buffers
Closes #254 Updates hajimehoshi/ebiten#3173
1 parent b2e2cd5 commit b1d8c7c

File tree

1 file changed

+27
-8
lines changed

1 file changed

+27
-8
lines changed

internal/mux/mux.go

+27-8
Original file line numberDiff line numberDiff line change
@@ -175,7 +175,7 @@ type playerImpl struct {
175175
volume float64
176176
err error
177177
state playerState
178-
tmpbuf []byte
178+
bufPool *sync.Pool
179179
buf []byte
180180
eof bool
181181
bufferSize int
@@ -246,15 +246,32 @@ func (p *playerImpl) setBufferSize(bufferSize int) {
246246
p.bufferSize = p.mux.defaultBufferSize()
247247
}
248248
if orig != p.bufferSize {
249-
p.tmpbuf = nil
249+
p.bufPool = &sync.Pool{
250+
New: func() interface{} {
251+
buf := make([]byte, p.bufferSize)
252+
return &buf
253+
},
254+
}
250255
}
251256
}
252257

253-
func (p *playerImpl) ensureTmpBuf() []byte {
254-
if p.tmpbuf == nil {
255-
p.tmpbuf = make([]byte, p.bufferSize)
258+
func (p *playerImpl) getTmpBuf() ([]byte, func()) {
259+
// The returned buffer could be accessed regardless of the mutex m (#254).
260+
// In order to oavoid races, use a sync.Pool.
261+
// On the other hand, the calls of getTmpBuf itself should be protected by the mutex m,
262+
// then accessing p.bufPool doesn't cause races.
263+
if p.bufPool == nil {
264+
p.bufPool = &sync.Pool{
265+
New: func() interface{} {
266+
buf := make([]byte, p.bufferSize)
267+
return &buf
268+
},
269+
}
270+
}
271+
buf := p.bufPool.Get().(*[]byte)
272+
return *buf, func() {
273+
p.bufPool.Put(buf)
256274
}
257-
return p.tmpbuf
258275
}
259276

260277
// read reads the source to buf.
@@ -296,7 +313,8 @@ func (p *playerImpl) playImpl() {
296313
p.state = playerPlay
297314

298315
if !p.eof {
299-
buf := p.ensureTmpBuf()
316+
buf, free := p.getTmpBuf()
317+
defer free()
300318
for len(p.buf) < p.bufferSize {
301319
n, err := p.read(buf)
302320
if err != nil && err != io.EOF {
@@ -525,7 +543,8 @@ func (p *playerImpl) readSourceToBuffer() int {
525543
return 0
526544
}
527545

528-
buf := p.ensureTmpBuf()
546+
buf, free := p.getTmpBuf()
547+
defer free()
529548
n, err := p.read(buf)
530549

531550
if err != nil && err != io.EOF {

0 commit comments

Comments
 (0)