aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPéter Szilágyi <peterke@gmail.com>2015-04-28 15:28:04 +0800
committerPéter Szilágyi <peterke@gmail.com>2015-04-28 15:28:04 +0800
commit4992765032b4318f3f5b4940a553b4e552c55963 (patch)
tree7c588f14e8b6fe0ea444b5f4fad720bc9051348b
parent437cf4b3acf1b5a4efde64aacaacdf14289010d1 (diff)
downloaddexon-4992765032b4318f3f5b4940a553b4e552c55963.tar.gz
dexon-4992765032b4318f3f5b4940a553b4e552c55963.tar.zst
dexon-4992765032b4318f3f5b4940a553b4e552c55963.zip
p2p/discover: fix goroutine leak due to blocking on sync.Once
-rw-r--r--p2p/discover/database.go35
-rw-r--r--p2p/discover/table.go2
2 files changed, 24 insertions, 13 deletions
diff --git a/p2p/discover/database.go b/p2p/discover/database.go
index 48539a6c9..d966a6ac1 100644
--- a/p2p/discover/database.go
+++ b/p2p/discover/database.go
@@ -177,23 +177,34 @@ func (db *nodeDB) updateNode(node *Node) error {
return db.lvl.Put(makeKey(node.ID, nodeDBDiscoverRoot), blob, nil)
}
+// ensureExpirer is a small helper method ensuring that the data expiration
+// mechanism is running. If the expiration goroutine is already running, this
+// method simply returns.
+//
+// The goal is to start the data evacuation only after the network successfully
+// bootstrapped itself (to prevent dumping potentially useful seed nodes). Since
+// it would require significant overhead to exactly trace the first successful
+// convergence, it's simpler to "ensure" the correct state when an appropriate
+// condition occurs (i.e. a successful bonding), and discard further events.
+func (db *nodeDB) ensureExpirer() {
+ db.runner.Do(func() { go db.expirer() })
+}
+
// expirer should be started in a go routine, and is responsible for looping ad
// infinitum and dropping stale data from the database.
func (db *nodeDB) expirer() {
- db.runner.Do(func() {
- tick := time.Tick(nodeDBCleanupCycle)
- for {
- select {
- case <-tick:
- if err := db.expireNodes(); err != nil {
- glog.V(logger.Error).Infof("Failed to expire nodedb items: %v", err)
- }
-
- case <-db.quit:
- return
+ tick := time.Tick(nodeDBCleanupCycle)
+ for {
+ select {
+ case <-tick:
+ if err := db.expireNodes(); err != nil {
+ glog.V(logger.Error).Infof("Failed to expire nodedb items: %v", err)
}
+
+ case <-db.quit:
+ return
}
- })
+ }
}
// expireNodes iterates over the database and deletes all nodes that have not
diff --git a/p2p/discover/table.go b/p2p/discover/table.go
index 060aa7c09..d3fe373f4 100644
--- a/p2p/discover/table.go
+++ b/p2p/discover/table.go
@@ -335,7 +335,7 @@ func (tab *Table) ping(id NodeID, addr *net.UDPAddr) error {
}
// Pong received, update the database and return
tab.db.updateLastPong(id, time.Now())
- go tab.db.expirer()
+ tab.db.ensureExpirer()
return nil
}