Fix concurrent map access in bytespipe

When getting and returning a buffer, need to make sure to syncronize
access to the pools map.

Signed-off-by: Brian Goff <cpuguy83@gmail.com>
This commit is contained in:
Brian Goff 2016-05-12 10:04:05 -04:00
parent 8a7fc5c59d
commit 1d2a9f2ace

View file

@ -20,7 +20,8 @@ var (
// ErrClosed is returned when Write is called on a closed BytesPipe. // ErrClosed is returned when Write is called on a closed BytesPipe.
ErrClosed = errors.New("write to closed BytesPipe") ErrClosed = errors.New("write to closed BytesPipe")
bufPools = make(map[int]*sync.Pool) bufPools = make(map[int]*sync.Pool)
bufPoolsLock sync.Mutex
) )
// BytesPipe is io.ReadWriteCloser which works similarly to pipe(queue). // BytesPipe is io.ReadWriteCloser which works similarly to pipe(queue).
@ -164,17 +165,21 @@ func (bp *BytesPipe) Read(p []byte) (n int, err error) {
func returnBuffer(b *fixedBuffer) { func returnBuffer(b *fixedBuffer) {
b.Reset() b.Reset()
bufPoolsLock.Lock()
pool := bufPools[b.Cap()] pool := bufPools[b.Cap()]
bufPoolsLock.Unlock()
if pool != nil { if pool != nil {
pool.Put(b) pool.Put(b)
} }
} }
func getBuffer(size int) *fixedBuffer { func getBuffer(size int) *fixedBuffer {
bufPoolsLock.Lock()
pool, ok := bufPools[size] pool, ok := bufPools[size]
if !ok { if !ok {
pool = &sync.Pool{New: func() interface{} { return &fixedBuffer{buf: make([]byte, 0, size)} }} pool = &sync.Pool{New: func() interface{} { return &fixedBuffer{buf: make([]byte, 0, size)} }}
bufPools[size] = pool bufPools[size] = pool
} }
bufPoolsLock.Unlock()
return pool.Get().(*fixedBuffer) return pool.Get().(*fixedBuffer)
} }