From 33a50e69f75e59612c7a5afb4d94bbe101bff7a2 Mon Sep 17 00:00:00 2001 From: beorn7 Date: Mon, 29 Feb 2016 16:33:22 +0100 Subject: [PATCH] Fix a deadlock Double acquisition of the RLock usually doesn't blow up, but if the write lock is called for between the two RLock's, we are deadlocked. This deadlock does not exist in release-0.17, BTW. --- retrieval/target.go | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/retrieval/target.go b/retrieval/target.go index 0ef92bfdb..bf00f7ca7 100644 --- a/retrieval/target.go +++ b/retrieval/target.go @@ -335,6 +335,7 @@ func (t *Target) path() string { } // wrapAppender wraps a SampleAppender for samples ingested from the target. +// RLock must be acquired by the caller. func (t *Target) wrapAppender(app storage.SampleAppender) storage.SampleAppender { // The relabelAppender has to be inside the label-modifying appenders // so the relabeling rules are applied to the correct label set. @@ -348,12 +349,12 @@ func (t *Target) wrapAppender(app storage.SampleAppender) storage.SampleAppender if t.scrapeConfig.HonorLabels { app = honorLabelsAppender{ SampleAppender: app, - labels: t.Labels(), + labels: t.unlockedLabels(), } } else { app = ruleLabelsAppender{ SampleAppender: app, - labels: t.Labels(), + labels: t.unlockedLabels(), } } return app @@ -361,6 +362,7 @@ func (t *Target) wrapAppender(app storage.SampleAppender) storage.SampleAppender // wrapReportingAppender wraps an appender for target status report samples. // It ignores any relabeling rules set for the target. +// RLock must not be acquired by the caller. func (t *Target) wrapReportingAppender(app storage.SampleAppender) storage.SampleAppender { return ruleLabelsAppender{ SampleAppender: app, @@ -647,6 +649,12 @@ func (t *Target) Labels() model.LabelSet { t.RLock() defer t.RUnlock() + return t.unlockedLabels() +} + +// unlockedLabels does the same as Labels but does not lock the mutex (useful +// for internal usage when the mutex is already locked). +func (t *Target) unlockedLabels() model.LabelSet { lset := make(model.LabelSet, len(t.labels)) for ln, lv := range t.labels { if !strings.HasPrefix(string(ln), model.ReservedLabelPrefix) {