From 0691b21a30380973bee4fcf3130cb0afb63c5fdf Mon Sep 17 00:00:00 2001 From: Conner Fromknecht Date: Mon, 7 May 2018 18:32:00 -0700 Subject: [PATCH] peer: improves disconnect handling This commit attempts to resolve some potential deadlock scenarios during a peer disconnect. Currently, writeMessage returns a nil error when disconnecting. This should have minimal impact on the writeHanlder, as the subsequent loop selects on the quit chan, and will cause it to exit. However, if this happens when sending the init message, the Start() method will attempt to proceed even though the peer has been disconnected. In addition, this commit changes the behavior of synchronous write errors, by using a non-blocking select. Though unlikely, this prevents any cases where multiple errors are returned, and the errors are not being pulled from the other side of the errChan. This removes any naked sends on the errChan from stalling the peer's shutdown. --- peer.go | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/peer.go b/peer.go index ad9dc946..41c1fc16 100644 --- a/peer.go +++ b/peer.go @@ -30,6 +30,9 @@ import ( var ( numNodes int32 + + // ErrPeerExiting signals that the peer received a disconnect request. + ErrPeerExiting = errors.Errorf("peer exiting") ) const ( @@ -1105,7 +1108,7 @@ func (p *peer) logWireMessage(msg lnwire.Message, read bool) { func (p *peer) writeMessage(msg lnwire.Message) error { // Simply exit if we're shutting down. if atomic.LoadInt32(&p.disconnect) != 0 { - return nil + return ErrPeerExiting } // TODO(roasbeef): add message summaries @@ -1154,8 +1157,8 @@ out: atomic.StoreInt64(&p.pingLastSend, now) } - // Write out the message to the socket, closing the - // 'sentChan' if it's non-nil, The 'sentChan' allows + // Write out the message to the socket, responding with + // error if `errChan` is non-nil. The `errChan` allows // callers to optionally synchronize sends with the // writeHandler. err := p.writeMessage(outMsg.msg) @@ -1169,7 +1172,7 @@ out: } case <-p.quit: - exitErr = errors.Errorf("peer exiting") + exitErr = ErrPeerExiting break out } } @@ -1263,7 +1266,7 @@ func (p *peer) queueMsg(msg lnwire.Message, errChan chan error) { case <-p.quit: peerLog.Tracef("Peer shutting down, could not enqueue msg.") if errChan != nil { - errChan <- fmt.Errorf("peer shutting down") + errChan <- ErrPeerExiting } } }