From 25c60b72eb8b916170cf85457fbe1cc2df61347a Mon Sep 17 00:00:00 2001 From: Matt Joiner Date: Tue, 19 Jan 2021 15:25:56 +1100 Subject: [PATCH] Fix race in writes to closed provider --- storage/sqlite/sqlite-storage.go | 25 ++++++++++++++++++------- 1 file changed, 18 insertions(+), 7 deletions(-) diff --git a/storage/sqlite/sqlite-storage.go b/storage/sqlite/sqlite-storage.go index 83be6e8d..cb2ab1b9 100644 --- a/storage/sqlite/sqlite-storage.go +++ b/storage/sqlite/sqlite-storage.go @@ -347,7 +347,8 @@ type provider struct { pool ConnPool writes chan<- writeRequest opts ProviderOpts - closed sync.Once + closeMu sync.RWMutex + closed bool closeErr error } @@ -382,12 +383,16 @@ func (p *provider) WriteConsecutiveChunks(prefix string, w io.Writer) (written i } func (me *provider) Close() error { - me.closed.Do(func() { - if me.writes != nil { - close(me.writes) - } - me.closeErr = me.pool.Close() - }) + me.closeMu.Lock() + defer me.closeMu.Unlock() + if me.closed { + return me.closeErr + } + if me.writes != nil { + close(me.writes) + } + me.closeErr = me.pool.Close() + me.closed = true return me.closeErr } @@ -481,11 +486,17 @@ func getLabels(skip int) pprof.LabelSet { func (p *provider) withConn(with withConn, write bool, skip int) error { if write && p.opts.BatchWrites { done := make(chan error) + p.closeMu.RLock() + if p.closed { + p.closeMu.RUnlock() + return errors.New("closed") + } p.writes <- writeRequest{ query: with, done: done, labels: getLabels(skip + 1), } + p.closeMu.RUnlock() return <-done } else { conn := p.pool.Get(context.TODO())