p2p: fix yet another disconnect hang
Peer.readLoop will only terminate if the connection is closed. Fix the hang by closing the connection before waiting for readLoop to terminate. This also removes the british disconnect procedure where we're waiting for the remote end to close the connection. I have confirmed with @subtly that cpp-ethereum doesn't adhere to it either.
This commit is contained in:
parent
79a6782c1c
commit
995fab2ebc
22
p2p/peer.go
22
p2p/peer.go
@ -4,7 +4,6 @@ import (
|
|||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"io/ioutil"
|
|
||||||
"net"
|
"net"
|
||||||
"sort"
|
"sort"
|
||||||
"sync"
|
"sync"
|
||||||
@ -21,7 +20,6 @@ const (
|
|||||||
baseProtocolMaxMsgSize = 10 * 1024 * 1024
|
baseProtocolMaxMsgSize = 10 * 1024 * 1024
|
||||||
|
|
||||||
pingInterval = 15 * time.Second
|
pingInterval = 15 * time.Second
|
||||||
disconnectGracePeriod = 2 * time.Second
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@ -129,39 +127,27 @@ func (p *Peer) run() DiscReason {
|
|||||||
case err := <-readErr:
|
case err := <-readErr:
|
||||||
if r, ok := err.(DiscReason); ok {
|
if r, ok := err.(DiscReason); ok {
|
||||||
reason = r
|
reason = r
|
||||||
break
|
} else {
|
||||||
}
|
|
||||||
// Note: We rely on protocols to abort if there is a write
|
// Note: We rely on protocols to abort if there is a write
|
||||||
// error. It might be more robust to handle them here as well.
|
// error. It might be more robust to handle them here as well.
|
||||||
p.DebugDetailf("Read error: %v\n", err)
|
p.DebugDetailf("Read error: %v\n", err)
|
||||||
p.conn.Close()
|
|
||||||
reason = DiscNetworkError
|
reason = DiscNetworkError
|
||||||
|
}
|
||||||
case err := <-p.protoErr:
|
case err := <-p.protoErr:
|
||||||
reason = discReasonForError(err)
|
reason = discReasonForError(err)
|
||||||
case reason = <-p.disc:
|
case reason = <-p.disc:
|
||||||
}
|
}
|
||||||
|
|
||||||
close(p.closed)
|
close(p.closed)
|
||||||
p.wg.Wait()
|
|
||||||
if reason != DiscNetworkError {
|
|
||||||
p.politeDisconnect(reason)
|
p.politeDisconnect(reason)
|
||||||
}
|
p.wg.Wait()
|
||||||
p.Debugf("Disconnected: %v\n", reason)
|
p.Debugf("Disconnected: %v\n", reason)
|
||||||
return reason
|
return reason
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *Peer) politeDisconnect(reason DiscReason) {
|
func (p *Peer) politeDisconnect(reason DiscReason) {
|
||||||
done := make(chan struct{})
|
if reason != DiscNetworkError {
|
||||||
go func() {
|
|
||||||
SendItems(p.rw, discMsg, uint(reason))
|
SendItems(p.rw, discMsg, uint(reason))
|
||||||
// Wait for the other side to close the connection.
|
|
||||||
// Discard any data that they send until then.
|
|
||||||
io.Copy(ioutil.Discard, p.conn)
|
|
||||||
close(done)
|
|
||||||
}()
|
|
||||||
select {
|
|
||||||
case <-done:
|
|
||||||
case <-time.After(disconnectGracePeriod):
|
|
||||||
}
|
}
|
||||||
p.conn.Close()
|
p.conn.Close()
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user