peer: ensure the version negotiation goroutine will always exit

In this commit, we patch a goroutine leak within the peer struct. This
goroutine leak can happen, if the remote side fails to actually finish
negotiation the protocol before our timeout ticker ticks. In this case,
the goroutine will be blocked on a send, as the channel is unfired. An
example trace from a btcd node I had on testnet showed:
```
3183 @ 0x42e78a 0x42e83e 0x40540b 0x4051a5 0x872f76 0x45bfc1
```

So, all instances of the goroutine failing to exit due to the remote
peer not finishing the p2p version negotiation handshake.

Our fix is simple: make the `negotiateErr' channel unbuffered. With this
simple change, we ensure that the goroutine will always exit even in the
case that the parent goroutine exists due to a timeout.  # Please enter
the commit message for your changes. Lines starting
This commit is contained in:
Olaoluwa Osuntokun 2018-07-21 17:41:23 -07:00
parent f673a4b563
commit 088eec67ec
No known key found for this signature in database
GPG key ID: 964EA263DD637C21

View file

@ -2053,7 +2053,7 @@ func (p *Peer) Disconnect() {
func (p *Peer) start() error {
log.Tracef("Starting peer %s", p)
negotiateErr := make(chan error)
negotiateErr := make(chan error, 1)
go func() {
if p.inbound {
negotiateErr <- p.negotiateInboundProtocol()