From 7371f1067bef109b61ecc5e741fcadb480596587 Mon Sep 17 00:00:00 2001 From: Jason Wilder Date: Wed, 3 May 2017 22:48:10 -0600 Subject: [PATCH] Fix deadlock in Index.ForEachMeasurementTagKey Index.ForEachMeasurementTagKey held an RLock while call the fn, if the fn made another call into the index which acquired an RLock and after another goroutine tried to acquire a Lock, it would deadlock. --- tsdb/index/inmem/inmem.go | 12 +++++++----- tsdb/meta.go | 5 +---- 2 files changed, 8 insertions(+), 9 deletions(-) diff --git a/tsdb/index/inmem/inmem.go b/tsdb/index/inmem/inmem.go index 940faa8d4b7..ca40cd8ce34 100644 --- a/tsdb/index/inmem/inmem.go +++ b/tsdb/index/inmem/inmem.go @@ -263,10 +263,13 @@ func (i *Index) MeasurementTagKeysByExpr(name []byte, expr influxql.Expr) (map[s // ForEachMeasurementTagKey iterates over all tag keys for a measurement. func (i *Index) ForEachMeasurementTagKey(name []byte, fn func(key []byte) error) error { + // Ensure we do not hold a lock on the index while fn executes in case fn tries + // to acquire a lock on the index again. If another goroutine has Lock, this will + // deadlock. i.mu.RLock() - defer i.mu.RUnlock() - mm := i.measurements[string(name)] + i.mu.RUnlock() + if mm == nil { return nil } @@ -537,9 +540,9 @@ func (i *Index) DropSeries(key []byte) error { // ForEachMeasurementSeriesByExpr iterates over all series in a measurement filtered by an expression. func (i *Index) ForEachMeasurementSeriesByExpr(name []byte, expr influxql.Expr, fn func(tags models.Tags) error) error { i.mu.RLock() - defer i.mu.RUnlock() - mm := i.measurements[string(name)] + i.mu.RUnlock() + if mm == nil { return nil } @@ -731,7 +734,6 @@ type ShardIndex struct { // CreateSeriesListIfNotExists creates a list of series if they doesn't exist in bulk. func (idx *ShardIndex) CreateSeriesListIfNotExists(keys, names [][]byte, tagsSlice []models.Tags) error { - keys, names, tagsSlice = idx.assignExistingSeries(idx.id, keys, names, tagsSlice) if len(keys) == 0 { return nil diff --git a/tsdb/meta.go b/tsdb/meta.go index b127c33899f..8d8ffae6ada 100644 --- a/tsdb/meta.go +++ b/tsdb/meta.go @@ -287,12 +287,9 @@ func (m *Measurement) ForEachSeriesByExpr(condition influxql.Expr, fn func(tags return err } - m.mu.RLock() - defer m.mu.RUnlock() - // Iterate over each series. for _, id := range ids { - s := m.seriesByID[id] + s := m.SeriesByID(id) if err := fn(s.Tags()); err != nil { return err }