From e14e2a878ed2795c50e110d58ec48f961025fb39 Mon Sep 17 00:00:00 2001 From: Peter Bourgon Date: Thu, 1 Oct 2015 14:42:01 +0200 Subject: [PATCH] Make report swapping less fragile --- probe/main.go | 47 ++++++++++++++++++++++++++--------------------- 1 file changed, 26 insertions(+), 21 deletions(-) diff --git a/probe/main.go b/probe/main.go index eacbc2cf9..095e5c90d 100644 --- a/probe/main.go +++ b/probe/main.go @@ -159,10 +159,8 @@ func main() { defer func() { done.Wait() }() // second, wait for the main loops to be killed defer close(quit) // first, kill the main loops - var ( - rpt = report.MakeReport() - rptLock = sync.Mutex{} - ) + var rpt syncReport + rpt.swap(report.MakeReport()) go func() { defer done.Done() @@ -178,16 +176,10 @@ func main() { } } - rptLock.Lock() - localReport := rpt.Copy() - rptLock.Unlock() - + localReport := rpt.copy() localReport = localReport.Merge(doReport(reporters)) localReport = Apply(localReport, taggers) - - rptLock.Lock() - rpt = localReport - rptLock.Unlock() + rpt.swap(localReport) if took := time.Since(start); took > *spyInterval { log.Printf("report generation took too long (%s)", took) @@ -202,21 +194,15 @@ func main() { go func() { defer done.Done() var ( - pubTick = time.Tick(*publishInterval) - p = xfer.NewReportPublisher(publishers) - localReport = report.MakeReport() + pubTick = time.Tick(*publishInterval) + p = xfer.NewReportPublisher(publishers) ) for { select { case <-pubTick: publishTicks.WithLabelValues().Add(1) - - rptLock.Lock() - localReport = rpt - rpt = report.MakeReport() - rptLock.Unlock() - + localReport := rpt.swap(report.MakeReport()) localReport.Window = *publishInterval if err := p.Publish(localReport); err != nil { log.Printf("publish: %v", err) @@ -256,3 +242,22 @@ func interrupt() <-chan os.Signal { signal.Notify(c, syscall.SIGINT, syscall.SIGTERM) return c } + +type syncReport struct { + mtx sync.RWMutex + rpt report.Report +} + +func (r *syncReport) swap(other report.Report) report.Report { + r.mtx.Lock() + defer r.mtx.Unlock() + old := r.rpt + r.rpt = other + return old +} + +func (r *syncReport) copy() report.Report { + r.mtx.RLock() + defer r.mtx.RUnlock() + return r.rpt.Copy() +}