Merge branch 'master' of https://github.com/grpc/grpc-go into race-fix
This commit is contained in:
@ -252,7 +252,7 @@ func Dial(target string, opts ...DialOption) (*ClientConn, error) {
|
|||||||
waitC := make(chan error, 1)
|
waitC := make(chan error, 1)
|
||||||
go func() {
|
go func() {
|
||||||
for _, a := range addrs {
|
for _, a := range addrs {
|
||||||
if err := cc.newAddrConn(a, false); err != nil {
|
if err := cc.resetAddrConn(a, false, nil); err != nil {
|
||||||
waitC <- err
|
waitC <- err
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -349,11 +349,12 @@ func (cc *ClientConn) lbWatcher() {
|
|||||||
}
|
}
|
||||||
if !keep {
|
if !keep {
|
||||||
del = append(del, c)
|
del = append(del, c)
|
||||||
|
delete(cc.conns, c.addr)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
cc.mu.Unlock()
|
cc.mu.Unlock()
|
||||||
for _, a := range add {
|
for _, a := range add {
|
||||||
cc.newAddrConn(a, true)
|
cc.resetAddrConn(a, true, nil)
|
||||||
}
|
}
|
||||||
for _, c := range del {
|
for _, c := range del {
|
||||||
c.tearDown(errConnDrain)
|
c.tearDown(errConnDrain)
|
||||||
@ -361,7 +362,10 @@ func (cc *ClientConn) lbWatcher() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (cc *ClientConn) newAddrConn(addr Address, skipWait bool) error {
|
// resetAddrConn creates an addrConn for addr and adds it to cc.conns.
|
||||||
|
// If there is an old addrConn for addr, it will be torn down, using errTearDown as the reason.
|
||||||
|
// If errTearDown is nil, errConnDrain will be used instead.
|
||||||
|
func (cc *ClientConn) resetAddrConn(addr Address, skipWait bool, errTearDown error) error {
|
||||||
ac := &addrConn{
|
ac := &addrConn{
|
||||||
cc: cc,
|
cc: cc,
|
||||||
addr: addr,
|
addr: addr,
|
||||||
@ -397,13 +401,27 @@ func (cc *ClientConn) newAddrConn(addr Address, skipWait bool) error {
|
|||||||
ac.cc.mu.Unlock()
|
ac.cc.mu.Unlock()
|
||||||
if stale != nil {
|
if stale != nil {
|
||||||
// There is an addrConn alive on ac.addr already. This could be due to
|
// There is an addrConn alive on ac.addr already. This could be due to
|
||||||
// i) stale's Close is undergoing;
|
// 1) stale's Close is undergoing;
|
||||||
// ii) a buggy Balancer notifies duplicated Addresses.
|
// 2) a buggy Balancer notifies duplicated Addresses;
|
||||||
stale.tearDown(errConnDrain)
|
// 3) goaway was received, a new ac will replace the old ac.
|
||||||
|
// The old ac should be deleted from cc.conns, but the
|
||||||
|
// underlying transport should drain rather than close.
|
||||||
|
if errTearDown == nil {
|
||||||
|
// errTearDown is nil if resetAddrConn is called by
|
||||||
|
// 1) Dial
|
||||||
|
// 2) lbWatcher
|
||||||
|
// In both cases, the stale ac should drain, not close.
|
||||||
|
stale.tearDown(errConnDrain)
|
||||||
|
} else {
|
||||||
|
stale.tearDown(errTearDown)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// skipWait may overwrite the decision in ac.dopts.block.
|
// skipWait may overwrite the decision in ac.dopts.block.
|
||||||
if ac.dopts.block && !skipWait {
|
if ac.dopts.block && !skipWait {
|
||||||
if err := ac.resetTransport(false); err != nil {
|
if err := ac.resetTransport(false); err != nil {
|
||||||
|
ac.cc.mu.Lock()
|
||||||
|
delete(ac.cc.conns, ac.addr)
|
||||||
|
ac.cc.mu.Unlock()
|
||||||
ac.tearDown(err)
|
ac.tearDown(err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -414,6 +432,9 @@ func (cc *ClientConn) newAddrConn(addr Address, skipWait bool) error {
|
|||||||
go func() {
|
go func() {
|
||||||
if err := ac.resetTransport(false); err != nil {
|
if err := ac.resetTransport(false); err != nil {
|
||||||
grpclog.Printf("Failed to dial %s: %v; please retry.", ac.addr.Addr, err)
|
grpclog.Printf("Failed to dial %s: %v; please retry.", ac.addr.Addr, err)
|
||||||
|
ac.cc.mu.Lock()
|
||||||
|
delete(ac.cc.conns, ac.addr)
|
||||||
|
ac.cc.mu.Unlock()
|
||||||
ac.tearDown(err)
|
ac.tearDown(err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -641,11 +662,10 @@ func (ac *addrConn) transportMonitor() {
|
|||||||
// In both cases, a new ac is created.
|
// In both cases, a new ac is created.
|
||||||
select {
|
select {
|
||||||
case <-t.Error():
|
case <-t.Error():
|
||||||
ac.tearDown(errNetworkIO)
|
ac.cc.resetAddrConn(ac.addr, true, errNetworkIO)
|
||||||
default:
|
default:
|
||||||
ac.tearDown(errConnDrain)
|
ac.cc.resetAddrConn(ac.addr, true, errConnDrain)
|
||||||
}
|
}
|
||||||
ac.cc.newAddrConn(ac.addr, true)
|
|
||||||
return
|
return
|
||||||
case <-t.Error():
|
case <-t.Error():
|
||||||
select {
|
select {
|
||||||
@ -653,8 +673,7 @@ func (ac *addrConn) transportMonitor() {
|
|||||||
t.Close()
|
t.Close()
|
||||||
return
|
return
|
||||||
case <-t.GoAway():
|
case <-t.GoAway():
|
||||||
ac.tearDown(errNetworkIO)
|
ac.cc.resetAddrConn(ac.addr, true, errNetworkIO)
|
||||||
ac.cc.newAddrConn(ac.addr, true)
|
|
||||||
return
|
return
|
||||||
default:
|
default:
|
||||||
}
|
}
|
||||||
@ -715,16 +734,10 @@ func (ac *addrConn) wait(ctx context.Context, failFast bool) (transport.ClientTr
|
|||||||
// TODO(zhaoq): Make this synchronous to avoid unbounded memory consumption in
|
// TODO(zhaoq): Make this synchronous to avoid unbounded memory consumption in
|
||||||
// some edge cases (e.g., the caller opens and closes many addrConn's in a
|
// some edge cases (e.g., the caller opens and closes many addrConn's in a
|
||||||
// tight loop.
|
// tight loop.
|
||||||
|
// tearDown doesn't remove ac from ac.cc.conns.
|
||||||
func (ac *addrConn) tearDown(err error) {
|
func (ac *addrConn) tearDown(err error) {
|
||||||
ac.mu.Lock()
|
ac.mu.Lock()
|
||||||
defer func() {
|
defer ac.mu.Unlock()
|
||||||
ac.mu.Unlock()
|
|
||||||
ac.cc.mu.Lock()
|
|
||||||
if ac.cc.conns != nil {
|
|
||||||
delete(ac.cc.conns, ac.addr)
|
|
||||||
}
|
|
||||||
ac.cc.mu.Unlock()
|
|
||||||
}()
|
|
||||||
if ac.down != nil {
|
if ac.down != nil {
|
||||||
ac.down(downErrorf(false, false, "%v", err))
|
ac.down(downErrorf(false, false, "%v", err))
|
||||||
ac.down = nil
|
ac.down = nil
|
||||||
|
Reference in New Issue
Block a user