From 6970f725c9b6cde00069fc0d1bc54c0be4cafe1c Mon Sep 17 00:00:00 2001 From: Chris Marchbanks Date: Wed, 9 Oct 2019 07:52:29 -0600 Subject: [PATCH] Fix panic in ARM builds of Prometheus (#6110) An extra sync.Pool was added during a refactor which caused some 64 bit, atomically accessed variables to no longer be 64 bit aligned. By moving all atomically accessed variables to the beginning of the struct they are guaranteed to be 64 bit aligned. Signed-off-by: Chris Marchbanks --- storage/remote/ewma.go | 13 ++++++++----- storage/remote/intern.go | 5 ++++- tsdb/db.go | 2 +- tsdb/head.go | 14 ++++++++------ 4 files changed, 21 insertions(+), 13 deletions(-) diff --git a/storage/remote/ewma.go b/storage/remote/ewma.go index d1ba27565..88cc79d75 100644 --- a/storage/remote/ewma.go +++ b/storage/remote/ewma.go @@ -21,12 +21,15 @@ import ( // ewmaRate tracks an exponentially weighted moving average of a per-second rate. type ewmaRate struct { + // Keep all 64bit atomically accessed variables at the top of this struct. + // See https://golang.org/pkg/sync/atomic/#pkg-note-BUG for more info. newEvents int64 - alpha float64 - interval time.Duration - lastRate float64 - init bool - mutex sync.Mutex + + alpha float64 + interval time.Duration + lastRate float64 + init bool + mutex sync.Mutex } // newEWMARate always allocates a new ewmaRate, as this guarantees the atomically diff --git a/storage/remote/intern.go b/storage/remote/intern.go index 5afa9a817..9ae6a569c 100644 --- a/storage/remote/intern.go +++ b/storage/remote/intern.go @@ -40,8 +40,11 @@ type pool struct { } type entry struct { - s string + // Keep all 64bit atomically accessed variables at the top of this struct. + // See https://golang.org/pkg/sync/atomic/#pkg-note-BUG for more info. refs int64 + + s string } func newPool() *pool { diff --git a/tsdb/db.go b/tsdb/db.go index e29aedf5b..35fba3b43 100644 --- a/tsdb/db.go +++ b/tsdb/db.go @@ -216,7 +216,7 @@ func newDBMetrics(db *DB, r prometheus.Registerer) *dbMetrics { db.mtx.RLock() defer db.mtx.RUnlock() if len(db.blocks) == 0 { - return float64(db.head.minTime) + return float64(db.head.MinTime()) } return float64(db.blocks[0].meta.MinTime) }) diff --git a/tsdb/head.go b/tsdb/head.go index 9fbe07c9b..42ebf4b9d 100644 --- a/tsdb/head.go +++ b/tsdb/head.go @@ -61,18 +61,20 @@ var ( // Head handles reads and writes of time series data within a time window. type Head struct { - chunkRange int64 + // Keep all 64bit atomically accessed variables at the top of this struct. + // See https://golang.org/pkg/sync/atomic/#pkg-note-BUG for more info. + chunkRange int64 + numSeries uint64 + minTime, maxTime int64 // Current min and max of the samples included in the head. + minValidTime int64 // Mint allowed to be added to the head. It shouldn't be lower than the maxt of the last persisted block. + lastSeriesID uint64 + metrics *headMetrics wal *wal.WAL logger log.Logger appendPool sync.Pool seriesPool sync.Pool bytesPool sync.Pool - numSeries uint64 - - minTime, maxTime int64 // Current min and max of the samples included in the head. - minValidTime int64 // Mint allowed to be added to the head. It shouldn't be lower than the maxt of the last persisted block. - lastSeriesID uint64 // All series addressable by their ID or hash. series *stripeSeries