p2p/simulations: fix deadlock in Network.GetRandomDownNode()

Problem: GetRandomDownNode() locks -> getDownNodeIDs() ->
GetNodes() tries to lock -> deadlock

On Network type, unexported functions must assume that `net.lock`
is already acquired and should not call exported functions which
might try to lock again.
This commit is contained in:
Ferenc Szabo 2019-02-15 11:59:54 +01:00
parent f2aba104b9
commit 316dac5ff4

View file

@ -377,6 +377,14 @@ func (net *Network) GetNode(id enode.ID) *Node {
return net.getNode(id) return net.getNode(id)
} }
func (net *Network) getNode(id enode.ID) *Node {
i, found := net.nodeMap[id]
if !found {
return nil
}
return net.Nodes[i]
}
// GetNode gets the node with the given name, returning nil if the node does // GetNode gets the node with the given name, returning nil if the node does
// not exist // not exist
func (net *Network) GetNodeByName(name string) *Node { func (net *Network) GetNodeByName(name string) *Node {
@ -399,16 +407,12 @@ func (net *Network) GetNodes() (nodes []*Node) {
net.lock.RLock() net.lock.RLock()
defer net.lock.RUnlock() defer net.lock.RUnlock()
nodes = append(nodes, net.Nodes...) return net.getNodes()
return nodes
} }
func (net *Network) getNode(id enode.ID) *Node { func (net *Network) getNodes() (nodes []*Node) {
i, found := net.nodeMap[id] nodes = append(nodes, net.Nodes...)
if !found { return nodes
return nil
}
return net.Nodes[i]
} }
// GetRandomUpNode returns a random node on the network, which is running. // GetRandomUpNode returns a random node on the network, which is running.
@ -435,7 +439,7 @@ func (net *Network) GetRandomDownNode(excludeIDs ...enode.ID) *Node {
} }
func (net *Network) getDownNodeIDs() (ids []enode.ID) { func (net *Network) getDownNodeIDs() (ids []enode.ID) {
for _, node := range net.GetNodes() { for _, node := range net.getNodes() {
if !node.Up() { if !node.Up() {
ids = append(ids, node.ID()) ids = append(ids, node.ID())
} }