From 1b916f89c154e76b8733db51ab738f6eaec0ab39 Mon Sep 17 00:00:00 2001 From: Elad Nachmias Date: Wed, 16 Jan 2019 20:44:50 +0530 Subject: [PATCH 1/3] swarm/network: fix data race on TestService bucket caused by copying struct content without synchronisation --- p2p/simulations/events.go | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/p2p/simulations/events.go b/p2p/simulations/events.go index 9b2a990e07e6..1f40c9437d6a 100644 --- a/p2p/simulations/events.go +++ b/p2p/simulations/events.go @@ -73,8 +73,7 @@ func NewEvent(v interface{}) *Event { switch v := v.(type) { case *Node: event.Type = EventTypeNode - node := *v - event.Node = &node + event.Node = v case *Conn: event.Type = EventTypeConn conn := *v From f1a242793b5de24ed1c7d73a5308977a9a6ded34 Mon Sep 17 00:00:00 2001 From: Elad Nachmias Date: Fri, 18 Jan 2019 15:03:49 +0700 Subject: [PATCH 2/3] p2p/simulations: changed NewEvent function to be used under network lock to avoid possible data race --- p2p/simulations/events.go | 3 ++- p2p/simulations/network.go | 15 ++++++++++----- 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/p2p/simulations/events.go b/p2p/simulations/events.go index 1f40c9437d6a..9b2a990e07e6 100644 --- a/p2p/simulations/events.go +++ b/p2p/simulations/events.go @@ -73,7 +73,8 @@ func NewEvent(v interface{}) *Event { switch v := v.(type) { case *Node: event.Type = EventTypeNode - event.Node = v + node := *v + event.Node = &node case *Conn: event.Type = EventTypeConn conn := *v diff --git a/p2p/simulations/network.go b/p2p/simulations/network.go index 86f7dc9bef44..ffe1f43a9d8d 100644 --- a/p2p/simulations/network.go +++ b/p2p/simulations/network.go @@ -168,7 +168,6 @@ func (net *Network) Start(id enode.ID) error { // snapshots func (net *Network) startWithSnapshots(id enode.ID, snapshots map[string][]byte) error { net.lock.Lock() - defer net.lock.Unlock() node := net.getNode(id) if node == nil { @@ -184,8 +183,10 @@ func (net *Network) startWithSnapshots(id enode.ID, snapshots map[string][]byte) } node.Up = true log.Info("Started node", "id", id) + ev := NewEvent(node) + net.lock.Unlock() - net.events.Send(NewEvent(node)) + net.events.Send(ev) // subscribe to peer events client, err := node.Client() @@ -209,13 +210,14 @@ func (net *Network) watchPeerEvents(id enode.ID, events chan *p2p.PeerEvent, sub // assume the node is now down net.lock.Lock() - defer net.lock.Unlock() node := net.getNode(id) if node == nil { return } node.Up = false - net.events.Send(NewEvent(node)) + ev := NewEvent(node) + net.lock.Unlock() + net.events.Send(ev) }() for { select { @@ -270,7 +272,10 @@ func (net *Network) Stop(id enode.ID) error { return err } log.Info("Stopped node", "id", id, "err", err) - net.events.Send(ControlEvent(node)) + net.lock.Lock() + ev := ControlEvent(node) + net.lock.Unlock() + net.events.Send(ev) return nil } From 8ec258ab1d9403ed75d1a4d13f0d5e81a5bf07d4 Mon Sep 17 00:00:00 2001 From: Elad Nachmias Date: Fri, 18 Jan 2019 20:53:51 +0700 Subject: [PATCH 3/3] p2p/simulations: address data race pr comments --- p2p/simulations/network.go | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/p2p/simulations/network.go b/p2p/simulations/network.go index ffe1f43a9d8d..6edcefc5320f 100644 --- a/p2p/simulations/network.go +++ b/p2p/simulations/network.go @@ -171,13 +171,16 @@ func (net *Network) startWithSnapshots(id enode.ID, snapshots map[string][]byte) node := net.getNode(id) if node == nil { + net.lock.Unlock() return fmt.Errorf("node %v does not exist", id) } if node.Up { + net.lock.Unlock() return fmt.Errorf("node %v already up", id) } log.Trace("Starting node", "id", id, "adapter", net.nodeAdapter.Name()) if err := node.Start(snapshots); err != nil { + net.lock.Unlock() log.Warn("Node startup failed", "id", id, "err", err) return err } @@ -210,13 +213,14 @@ func (net *Network) watchPeerEvents(id enode.ID, events chan *p2p.PeerEvent, sub // assume the node is now down net.lock.Lock() + defer net.lock.Unlock() + node := net.getNode(id) if node == nil { return } node.Up = false ev := NewEvent(node) - net.lock.Unlock() net.events.Send(ev) }() for { @@ -256,9 +260,11 @@ func (net *Network) Stop(id enode.ID) error { net.lock.Lock() node := net.getNode(id) if node == nil { + net.lock.Unlock() return fmt.Errorf("node %v does not exist", id) } if !node.Up { + net.lock.Unlock() return fmt.Errorf("node %v already down", id) } node.Up = false