From 74c38902ecec507675e1e9033500addc87e4b7b0 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jano=C5=A1=20Gulja=C5=A1?= <janos@users.noreply.github.com>
Date: Tue, 29 Jan 2019 15:19:54 +0100
Subject: [PATCH] p2p/protocols: fix possible metrics loss in AccountingMetrics
 (#18956)

---
 p2p/protocols/reporter.go | 15 +++++++++++++++
 1 file changed, 15 insertions(+)

diff --git a/p2p/protocols/reporter.go b/p2p/protocols/reporter.go
index 215d4fe31..9612b4a4d 100644
--- a/p2p/protocols/reporter.go
+++ b/p2p/protocols/reporter.go
@@ -36,6 +36,13 @@ type AccountingMetrics struct {
 //for a graceful cleanup
 func (am *AccountingMetrics) Close() {
 	close(am.reporter.quit)
+	// wait for reporter loop to finish saving metrics
+	// before reporter database is closed
+	select {
+	case <-time.After(10 * time.Second):
+		log.Error("accounting metrics reporter timeout")
+	case <-am.reporter.done:
+	}
 	am.reporter.db.Close()
 }
 
@@ -46,6 +53,7 @@ type reporter struct {
 	interval time.Duration    //duration at which the reporter will persist metrics
 	db       *leveldb.DB      //the actual DB
 	quit     chan struct{}    //quit the reporter loop
+	done     chan struct{}    //signal that reporter loop is done
 }
 
 //NewMetricsDB creates a new LevelDB instance used to persist metrics defined
@@ -92,6 +100,7 @@ func NewAccountingMetrics(r metrics.Registry, d time.Duration, path string) *Acc
 		interval: d,
 		db:       db,
 		quit:     make(chan struct{}),
+		done:     make(chan struct{}),
 	}
 
 	//run the go routine
@@ -106,6 +115,9 @@ func NewAccountingMetrics(r metrics.Registry, d time.Duration, path string) *Acc
 
 //run is the goroutine which periodically sends the metrics to the configured LevelDB
 func (r *reporter) run() {
+	// signal that the reporter loop is done
+	defer close(r.done)
+
 	intervalTicker := time.NewTicker(r.interval)
 
 	for {
@@ -121,6 +133,9 @@ func (r *reporter) run() {
 			}
 		case <-r.quit:
 			//graceful shutdown
+			if err := r.save(); err != nil {
+				log.Error("unable to send metrics to LevelDB", "err", err)
+			}
 			return
 		}
 	}
-- 
GitLab