mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-08-14 16:03:45 +00:00
Merge pull request #105 from ethersphere/network-testing-framework-lock-fixes
Prevent various deadlocks
This commit is contained in:
commit
8863324fff
4 changed files with 59 additions and 84 deletions
|
|
@ -228,7 +228,7 @@ func (self *Peer) Send(msg interface{}) error {
|
||||||
if !found {
|
if !found {
|
||||||
return errorf(ErrInvalidMsgType, "%v", code)
|
return errorf(ErrInvalidMsgType, "%v", code)
|
||||||
}
|
}
|
||||||
log.Trace(fmt.Sprintf("=> msg #%d TO %v : %v", code, self.ID(), msg))
|
log.Trace(fmt.Sprintf("=> msg %s#%d TO %v : %v", self.spec.Name, code, self.ID(), msg))
|
||||||
return p2p.Send(self.rw, code, msg)
|
return p2p.Send(self.rw, code, msg)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -257,7 +257,7 @@ func (self *Peer) handleIncoming(handle func(msg interface{}) error) error {
|
||||||
if err := msg.Decode(val); err != nil {
|
if err := msg.Decode(val); err != nil {
|
||||||
return errorf(ErrDecode, "<= %v: %v", msg, err)
|
return errorf(ErrDecode, "<= %v: %v", msg, err)
|
||||||
}
|
}
|
||||||
log.Trace(fmt.Sprintf("<= %v FROM %v %T %v", msg, self.ID(), val, val))
|
log.Trace(fmt.Sprintf("<= %s/%v FROM %v %T %v", self.spec.Name, msg, self.ID(), val, val))
|
||||||
|
|
||||||
// call the registered handler callbacks
|
// call the registered handler callbacks
|
||||||
// a registered callback take the decoded message as argument as an interface
|
// a registered callback take the decoded message as argument as an interface
|
||||||
|
|
@ -280,29 +280,24 @@ func (self *Peer) Handshake(ctx context.Context, hs interface{}) (interface{}, e
|
||||||
}
|
}
|
||||||
errc := make(chan error, 2)
|
errc := make(chan error, 2)
|
||||||
go func() {
|
go func() {
|
||||||
if err := self.Send(hs); err != nil {
|
errc <- self.Send(hs)
|
||||||
errc <- errorf(ErrHandshake, "cannot send: %v", err)
|
|
||||||
}
|
|
||||||
}()
|
}()
|
||||||
hsc := make(chan interface{})
|
var rhs interface{}
|
||||||
go func() {
|
go func() {
|
||||||
var rhs interface{}
|
errc <- self.handleIncoming(func(msg interface{}) error {
|
||||||
err := self.handleIncoming(func(msg interface{}) error {
|
|
||||||
rhs = msg
|
rhs = msg
|
||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
if err != nil {
|
|
||||||
errc <- err
|
|
||||||
return
|
|
||||||
}
|
|
||||||
hsc <- rhs
|
|
||||||
}()
|
}()
|
||||||
select {
|
for i := 0; i < 2; i++ {
|
||||||
case rhs := <-hsc:
|
select {
|
||||||
return rhs, nil
|
case err := <-errc:
|
||||||
case <-ctx.Done():
|
if err != nil {
|
||||||
return nil, ctx.Err()
|
return nil, errorf(ErrHandshake, err.Error())
|
||||||
case err := <-errc:
|
}
|
||||||
return nil, err
|
case <-ctx.Done():
|
||||||
|
return nil, ctx.Err()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
return rhs, nil
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -548,7 +548,11 @@ running:
|
||||||
c.flags |= trustedConn
|
c.flags |= trustedConn
|
||||||
}
|
}
|
||||||
// TODO: track in-progress inbound node IDs (pre-Peer) to avoid dialing them.
|
// TODO: track in-progress inbound node IDs (pre-Peer) to avoid dialing them.
|
||||||
c.cont <- srv.encHandshakeChecks(peers, c)
|
select {
|
||||||
|
case c.cont <- srv.encHandshakeChecks(peers, c):
|
||||||
|
case <-srv.quit:
|
||||||
|
break running
|
||||||
|
}
|
||||||
case c := <-srv.addpeer:
|
case c := <-srv.addpeer:
|
||||||
// At this point the connection is past the protocol handshake.
|
// At this point the connection is past the protocol handshake.
|
||||||
// Its capabilities are known and the remote identity is verified.
|
// Its capabilities are known and the remote identity is verified.
|
||||||
|
|
@ -569,7 +573,11 @@ running:
|
||||||
// The dialer logic relies on the assumption that
|
// The dialer logic relies on the assumption that
|
||||||
// dial tasks complete after the peer has been added or
|
// dial tasks complete after the peer has been added or
|
||||||
// discarded. Unblock the task last.
|
// discarded. Unblock the task last.
|
||||||
c.cont <- err
|
select {
|
||||||
|
case c.cont <- err:
|
||||||
|
case <-srv.quit:
|
||||||
|
break running
|
||||||
|
}
|
||||||
case pd := <-srv.delpeer:
|
case pd := <-srv.delpeer:
|
||||||
// A peer disconnected.
|
// A peer disconnected.
|
||||||
d := common.PrettyDuration(mclock.Now() - pd.created)
|
d := common.PrettyDuration(mclock.Now() - pd.created)
|
||||||
|
|
|
||||||
|
|
@ -74,14 +74,29 @@ func (s *SimAdapter) NewNode(config *NodeConfig) (Node, error) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
node := &SimNode{
|
n, err := node.New(&node.Config{
|
||||||
|
P2P: p2p.Config{
|
||||||
|
PrivateKey: config.PrivateKey,
|
||||||
|
MaxPeers: math.MaxInt32,
|
||||||
|
NoDiscovery: true,
|
||||||
|
Dialer: s,
|
||||||
|
EnableMsgEvents: false,
|
||||||
|
},
|
||||||
|
NoUSB: true,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
simNode := &SimNode{
|
||||||
ID: id,
|
ID: id,
|
||||||
config: config,
|
config: config,
|
||||||
|
node: n,
|
||||||
adapter: s,
|
adapter: s,
|
||||||
running: make(map[string]node.Service),
|
running: make(map[string]node.Service),
|
||||||
}
|
}
|
||||||
s.nodes[id] = node
|
s.nodes[id] = simNode
|
||||||
return node, nil
|
return simNode, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *SimAdapter) Dial(dest *discover.Node) (conn net.Conn, err error) {
|
func (s *SimAdapter) Dial(dest *discover.Node) (conn net.Conn, err error) {
|
||||||
|
|
@ -99,17 +114,11 @@ func (s *SimAdapter) Dial(dest *discover.Node) (conn net.Conn, err error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *SimAdapter) DialRPC(id discover.NodeID) (*rpc.Client, error) {
|
func (s *SimAdapter) DialRPC(id discover.NodeID) (*rpc.Client, error) {
|
||||||
simNode, ok := s.GetNode(id)
|
node, ok := s.GetNode(id)
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, fmt.Errorf("unknown node: %s", id)
|
return nil, fmt.Errorf("unknown node: %s", id)
|
||||||
}
|
}
|
||||||
simNode.lock.RLock()
|
handler, err := node.node.RPCHandler()
|
||||||
node := simNode.node
|
|
||||||
simNode.lock.RUnlock()
|
|
||||||
if node == nil {
|
|
||||||
return nil, errors.New("node not started")
|
|
||||||
}
|
|
||||||
handler, err := node.RPCHandler()
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
@ -164,13 +173,7 @@ func (self *SimNode) Client() (*rpc.Client, error) {
|
||||||
// ServeRPC serves RPC requests over the given connection by creating an
|
// ServeRPC serves RPC requests over the given connection by creating an
|
||||||
// in-process client to the node's RPC server
|
// in-process client to the node's RPC server
|
||||||
func (self *SimNode) ServeRPC(conn net.Conn) error {
|
func (self *SimNode) ServeRPC(conn net.Conn) error {
|
||||||
self.lock.RLock()
|
handler, err := self.node.RPCHandler()
|
||||||
node := self.node
|
|
||||||
self.lock.RUnlock()
|
|
||||||
if node == nil {
|
|
||||||
return errors.New("node not started")
|
|
||||||
}
|
|
||||||
handler, err := node.RPCHandler()
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
@ -181,9 +184,12 @@ func (self *SimNode) ServeRPC(conn net.Conn) error {
|
||||||
// Snapshots creates snapshots of the services by calling the
|
// Snapshots creates snapshots of the services by calling the
|
||||||
// simulation_snapshot RPC method
|
// simulation_snapshot RPC method
|
||||||
func (self *SimNode) Snapshots() (map[string][]byte, error) {
|
func (self *SimNode) Snapshots() (map[string][]byte, error) {
|
||||||
self.lock.Lock()
|
self.lock.RLock()
|
||||||
services := self.running
|
services := make(map[string]node.Service, len(self.running))
|
||||||
self.lock.Unlock()
|
for name, service := range self.running {
|
||||||
|
services[name] = service
|
||||||
|
}
|
||||||
|
self.lock.RUnlock()
|
||||||
if len(services) == 0 {
|
if len(services) == 0 {
|
||||||
return nil, errors.New("no running services")
|
return nil, errors.New("no running services")
|
||||||
}
|
}
|
||||||
|
|
@ -206,10 +212,6 @@ func (self *SimNode) Snapshots() (map[string][]byte, error) {
|
||||||
func (self *SimNode) Start(snapshots map[string][]byte) error {
|
func (self *SimNode) Start(snapshots map[string][]byte) error {
|
||||||
self.lock.Lock()
|
self.lock.Lock()
|
||||||
defer self.lock.Unlock()
|
defer self.lock.Unlock()
|
||||||
if self.node != nil {
|
|
||||||
return errors.New("node already started")
|
|
||||||
}
|
|
||||||
|
|
||||||
newService := func(name string) func(ctx *node.ServiceContext) (node.Service, error) {
|
newService := func(name string) func(ctx *node.ServiceContext) (node.Service, error) {
|
||||||
return func(nodeCtx *node.ServiceContext) (node.Service, error) {
|
return func(nodeCtx *node.ServiceContext) (node.Service, error) {
|
||||||
ctx := &ServiceContext{
|
ctx := &ServiceContext{
|
||||||
|
|
@ -230,59 +232,34 @@ func (self *SimNode) Start(snapshots map[string][]byte) error {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
node, err := node.New(&node.Config{
|
|
||||||
P2P: p2p.Config{
|
|
||||||
PrivateKey: self.config.PrivateKey,
|
|
||||||
MaxPeers: math.MaxInt32,
|
|
||||||
NoDiscovery: true,
|
|
||||||
Dialer: self.adapter,
|
|
||||||
EnableMsgEvents: false,
|
|
||||||
},
|
|
||||||
NoUSB: true,
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, name := range self.config.Services {
|
for _, name := range self.config.Services {
|
||||||
if err := node.Register(newService(name)); err != nil {
|
if err := self.node.Register(newService(name)); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := node.Start(); err != nil {
|
if err := self.node.Start(); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// create an in-process RPC client
|
// create an in-process RPC client
|
||||||
handler, err := node.RPCHandler()
|
handler, err := self.node.RPCHandler()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
self.client = rpc.DialInProc(handler)
|
self.client = rpc.DialInProc(handler)
|
||||||
|
|
||||||
self.node = node
|
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *SimNode) Stop() error {
|
func (self *SimNode) Stop() error {
|
||||||
self.lock.Lock()
|
return self.node.Stop()
|
||||||
defer self.lock.Unlock()
|
|
||||||
if self.node == nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
if err := self.node.Stop(); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
self.node = nil
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Services returns the underlying services
|
// Services returns the underlying services
|
||||||
func (self *SimNode) Services() []node.Service {
|
func (self *SimNode) Services() []node.Service {
|
||||||
self.lock.Lock()
|
self.lock.RLock()
|
||||||
defer self.lock.Unlock()
|
defer self.lock.RUnlock()
|
||||||
services := make([]node.Service, 0, len(self.running))
|
services := make([]node.Service, 0, len(self.running))
|
||||||
for _, service := range self.running {
|
for _, service := range self.running {
|
||||||
services = append(services, service)
|
services = append(services, service)
|
||||||
|
|
@ -291,11 +268,6 @@ func (self *SimNode) Services() []node.Service {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (self *SimNode) Server() *p2p.Server {
|
func (self *SimNode) Server() *p2p.Server {
|
||||||
self.lock.Lock()
|
|
||||||
defer self.lock.Unlock()
|
|
||||||
if self.node == nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
return self.node.Server()
|
return self.node.Server()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -595,7 +595,7 @@ func (k *Kademlia) gotNearestNeighbours(peers [][]byte) (got bool) {
|
||||||
for _, p := range peers {
|
for _, p := range peers {
|
||||||
pm[string(p)] = true
|
pm[string(p)] = true
|
||||||
}
|
}
|
||||||
k.EachConn(nil, 255, func(p OverlayConn, po int, nn bool) bool {
|
k.eachConn(nil, 255, func(p OverlayConn, po int, nn bool) bool {
|
||||||
if !nn {
|
if !nn {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue