Revert to using defers in addrbook. (#3025)

* Revert to using defers in addrbook.  ValidateBasic->Validate since it requires DNS

* Update CHANGELOG_PENDING
This commit is contained in:
Jae Kwon
2018-12-16 09:27:16 -08:00
committed by Ethan Buchman
parent 9fa959619a
commit 9a6dd96cba
8 changed files with 39 additions and 15 deletions

View File

@ -21,3 +21,5 @@ Special thanks to external contributors on this release:
### IMPROVEMENTS: ### IMPROVEMENTS:
### BUG FIXES: ### BUG FIXES:
- [\#3025](https://github.com/tendermint/tendermint/pull/3025) - Revert to using defers in addrbook. Fixes deadlocks in pex and consensus upon invalid ExternalAddr/ListenAddr configuration.

View File

@ -817,6 +817,11 @@ func makeNodeInfo(
nodeInfo.ListenAddr = lAddr nodeInfo.ListenAddr = lAddr
err := nodeInfo.Validate()
if err != nil {
panic(err)
}
return nodeInfo return nodeInfo
} }

View File

@ -175,6 +175,9 @@ func (na *NetAddress) Same(other interface{}) bool {
// String representation: <ID>@<IP>:<PORT> // String representation: <ID>@<IP>:<PORT>
func (na *NetAddress) String() string { func (na *NetAddress) String() string {
if na == nil {
return "<nil-NetAddress>"
}
if na.str == "" { if na.str == "" {
addrStr := na.DialString() addrStr := na.DialString()
if na.ID != "" { if na.ID != "" {
@ -186,6 +189,9 @@ func (na *NetAddress) String() string {
} }
func (na *NetAddress) DialString() string { func (na *NetAddress) DialString() string {
if na == nil {
return "<nil-NetAddress>"
}
return net.JoinHostPort( return net.JoinHostPort(
na.IP.String(), na.IP.String(),
strconv.FormatUint(uint64(na.Port), 10), strconv.FormatUint(uint64(na.Port), 10),

View File

@ -36,7 +36,7 @@ type nodeInfoAddress interface {
// nodeInfoTransport validates a nodeInfo and checks // nodeInfoTransport validates a nodeInfo and checks
// our compatibility with it. It's for use in the handshake. // our compatibility with it. It's for use in the handshake.
type nodeInfoTransport interface { type nodeInfoTransport interface {
ValidateBasic() error Validate() error
CompatibleWith(other NodeInfo) error CompatibleWith(other NodeInfo) error
} }
@ -103,7 +103,7 @@ func (info DefaultNodeInfo) ID() ID {
return info.ID_ return info.ID_
} }
// ValidateBasic checks the self-reported DefaultNodeInfo is safe. // Validate checks the self-reported DefaultNodeInfo is safe.
// It returns an error if there // It returns an error if there
// are too many Channels, if there are any duplicate Channels, // are too many Channels, if there are any duplicate Channels,
// if the ListenAddr is malformed, or if the ListenAddr is a host name // if the ListenAddr is malformed, or if the ListenAddr is a host name
@ -116,7 +116,7 @@ func (info DefaultNodeInfo) ID() ID {
// International clients could then use punycode (or we could use // International clients could then use punycode (or we could use
// url-encoding), and we just need to be careful with how we handle that in our // url-encoding), and we just need to be careful with how we handle that in our
// clients. (e.g. off by default). // clients. (e.g. off by default).
func (info DefaultNodeInfo) ValidateBasic() error { func (info DefaultNodeInfo) Validate() error {
// ID is already validated. // ID is already validated.

View File

@ -12,7 +12,7 @@ func TestNodeInfoValidate(t *testing.T) {
// empty fails // empty fails
ni := DefaultNodeInfo{} ni := DefaultNodeInfo{}
assert.Error(t, ni.ValidateBasic()) assert.Error(t, ni.Validate())
channels := make([]byte, maxNumChannels) channels := make([]byte, maxNumChannels)
for i := 0; i < maxNumChannels; i++ { for i := 0; i < maxNumChannels; i++ {
@ -68,13 +68,13 @@ func TestNodeInfoValidate(t *testing.T) {
// test case passes // test case passes
ni = testNodeInfo(nodeKey.ID(), name).(DefaultNodeInfo) ni = testNodeInfo(nodeKey.ID(), name).(DefaultNodeInfo)
ni.Channels = channels ni.Channels = channels
assert.NoError(t, ni.ValidateBasic()) assert.NoError(t, ni.Validate())
for _, tc := range testCases { for _, tc := range testCases {
ni := testNodeInfo(nodeKey.ID(), name).(DefaultNodeInfo) ni := testNodeInfo(nodeKey.ID(), name).(DefaultNodeInfo)
ni.Channels = channels ni.Channels = channels
tc.malleateNodeInfo(&ni) tc.malleateNodeInfo(&ni)
err := ni.ValidateBasic() err := ni.Validate()
if tc.expectErr { if tc.expectErr {
assert.Error(t, err, tc.testName) assert.Error(t, err, tc.testName)
} else { } else {

View File

@ -162,26 +162,29 @@ func (a *addrBook) FilePath() string {
// AddOurAddress one of our addresses. // AddOurAddress one of our addresses.
func (a *addrBook) AddOurAddress(addr *p2p.NetAddress) { func (a *addrBook) AddOurAddress(addr *p2p.NetAddress) {
a.Logger.Info("Add our address to book", "addr", addr)
a.mtx.Lock() a.mtx.Lock()
defer a.mtx.Unlock()
a.Logger.Info("Add our address to book", "addr", addr)
a.ourAddrs[addr.String()] = struct{}{} a.ourAddrs[addr.String()] = struct{}{}
a.mtx.Unlock()
} }
// OurAddress returns true if it is our address. // OurAddress returns true if it is our address.
func (a *addrBook) OurAddress(addr *p2p.NetAddress) bool { func (a *addrBook) OurAddress(addr *p2p.NetAddress) bool {
a.mtx.Lock() a.mtx.Lock()
defer a.mtx.Unlock()
_, ok := a.ourAddrs[addr.String()] _, ok := a.ourAddrs[addr.String()]
a.mtx.Unlock()
return ok return ok
} }
func (a *addrBook) AddPrivateIDs(IDs []string) { func (a *addrBook) AddPrivateIDs(IDs []string) {
a.mtx.Lock() a.mtx.Lock()
defer a.mtx.Unlock()
for _, id := range IDs { for _, id := range IDs {
a.privateIDs[p2p.ID(id)] = struct{}{} a.privateIDs[p2p.ID(id)] = struct{}{}
} }
a.mtx.Unlock()
} }
// AddAddress implements AddrBook // AddAddress implements AddrBook
@ -191,6 +194,7 @@ func (a *addrBook) AddPrivateIDs(IDs []string) {
func (a *addrBook) AddAddress(addr *p2p.NetAddress, src *p2p.NetAddress) error { func (a *addrBook) AddAddress(addr *p2p.NetAddress, src *p2p.NetAddress) error {
a.mtx.Lock() a.mtx.Lock()
defer a.mtx.Unlock() defer a.mtx.Unlock()
return a.addAddress(addr, src) return a.addAddress(addr, src)
} }
@ -198,6 +202,7 @@ func (a *addrBook) AddAddress(addr *p2p.NetAddress, src *p2p.NetAddress) error {
func (a *addrBook) RemoveAddress(addr *p2p.NetAddress) { func (a *addrBook) RemoveAddress(addr *p2p.NetAddress) {
a.mtx.Lock() a.mtx.Lock()
defer a.mtx.Unlock() defer a.mtx.Unlock()
ka := a.addrLookup[addr.ID] ka := a.addrLookup[addr.ID]
if ka == nil { if ka == nil {
return return
@ -211,14 +216,16 @@ func (a *addrBook) RemoveAddress(addr *p2p.NetAddress) {
func (a *addrBook) IsGood(addr *p2p.NetAddress) bool { func (a *addrBook) IsGood(addr *p2p.NetAddress) bool {
a.mtx.Lock() a.mtx.Lock()
defer a.mtx.Unlock() defer a.mtx.Unlock()
return a.addrLookup[addr.ID].isOld() return a.addrLookup[addr.ID].isOld()
} }
// HasAddress returns true if the address is in the book. // HasAddress returns true if the address is in the book.
func (a *addrBook) HasAddress(addr *p2p.NetAddress) bool { func (a *addrBook) HasAddress(addr *p2p.NetAddress) bool {
a.mtx.Lock() a.mtx.Lock()
defer a.mtx.Unlock()
ka := a.addrLookup[addr.ID] ka := a.addrLookup[addr.ID]
a.mtx.Unlock()
return ka != nil return ka != nil
} }
@ -292,6 +299,7 @@ func (a *addrBook) PickAddress(biasTowardsNewAddrs int) *p2p.NetAddress {
func (a *addrBook) MarkGood(addr *p2p.NetAddress) { func (a *addrBook) MarkGood(addr *p2p.NetAddress) {
a.mtx.Lock() a.mtx.Lock()
defer a.mtx.Unlock() defer a.mtx.Unlock()
ka := a.addrLookup[addr.ID] ka := a.addrLookup[addr.ID]
if ka == nil { if ka == nil {
return return
@ -306,6 +314,7 @@ func (a *addrBook) MarkGood(addr *p2p.NetAddress) {
func (a *addrBook) MarkAttempt(addr *p2p.NetAddress) { func (a *addrBook) MarkAttempt(addr *p2p.NetAddress) {
a.mtx.Lock() a.mtx.Lock()
defer a.mtx.Unlock() defer a.mtx.Unlock()
ka := a.addrLookup[addr.ID] ka := a.addrLookup[addr.ID]
if ka == nil { if ka == nil {
return return
@ -461,12 +470,13 @@ ADDRS_LOOP:
// ListOfKnownAddresses returns the new and old addresses. // ListOfKnownAddresses returns the new and old addresses.
func (a *addrBook) ListOfKnownAddresses() []*knownAddress { func (a *addrBook) ListOfKnownAddresses() []*knownAddress {
addrs := []*knownAddress{}
a.mtx.Lock() a.mtx.Lock()
defer a.mtx.Unlock()
addrs := []*knownAddress{}
for _, addr := range a.addrLookup { for _, addr := range a.addrLookup {
addrs = append(addrs, addr.copy()) addrs = append(addrs, addr.copy())
} }
a.mtx.Unlock()
return addrs return addrs
} }
@ -476,6 +486,7 @@ func (a *addrBook) ListOfKnownAddresses() []*knownAddress {
func (a *addrBook) Size() int { func (a *addrBook) Size() int {
a.mtx.Lock() a.mtx.Lock()
defer a.mtx.Unlock() defer a.mtx.Unlock()
return a.size() return a.size()
} }

View File

@ -24,7 +24,7 @@ type mockNodeInfo struct {
func (ni mockNodeInfo) ID() ID { return ni.addr.ID } func (ni mockNodeInfo) ID() ID { return ni.addr.ID }
func (ni mockNodeInfo) NetAddress() *NetAddress { return ni.addr } func (ni mockNodeInfo) NetAddress() *NetAddress { return ni.addr }
func (ni mockNodeInfo) ValidateBasic() error { return nil } func (ni mockNodeInfo) Validate() error { return nil }
func (ni mockNodeInfo) CompatibleWith(other NodeInfo) error { return nil } func (ni mockNodeInfo) CompatibleWith(other NodeInfo) error { return nil }
func AddPeerToSwitch(sw *Switch, peer Peer) { func AddPeerToSwitch(sw *Switch, peer Peer) {

View File

@ -350,7 +350,7 @@ func (mt *MultiplexTransport) upgrade(
} }
} }
if err := nodeInfo.ValidateBasic(); err != nil { if err := nodeInfo.Validate(); err != nil {
return nil, nil, ErrRejected{ return nil, nil, ErrRejected{
conn: c, conn: c,
err: err, err: err,