Skip to content

Commit 4554924

Browse files
authored
internal: fix deadlock during switch_balancer and NewSubConn() (#4536)
1 parent 2d3b1f9 commit 4554924

File tree

2 files changed

+15
-0
lines changed

2 files changed

+15
-0
lines changed

clientconn.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -711,7 +711,12 @@ func (cc *ClientConn) switchBalancer(name string) {
711711
return
712712
}
713713
if cc.balancerWrapper != nil {
714+
// Don't hold cc.mu while closing the balancers. The balancers may call
715+
// methods that require cc.mu (e.g. cc.NewSubConn()). Holding the mutex
716+
// would cause a deadlock in that case.
717+
cc.mu.Unlock()
714718
cc.balancerWrapper.close()
719+
cc.mu.Lock()
715720
}
716721

717722
builder := balancer.Get(name)

resolver_conn_wrapper.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,8 @@ type ccResolverWrapper struct {
3939
resolver resolver.Resolver
4040
done *grpcsync.Event
4141
curState resolver.State
42+
43+
incomingMu sync.Mutex // Synchronizes all the incoming calls.
4244
}
4345

4446
// newCCResolverWrapper uses the resolver.Builder to build a Resolver and
@@ -90,6 +92,8 @@ func (ccr *ccResolverWrapper) close() {
9092
}
9193

9294
func (ccr *ccResolverWrapper) UpdateState(s resolver.State) error {
95+
ccr.incomingMu.Lock()
96+
defer ccr.incomingMu.Unlock()
9397
if ccr.done.HasFired() {
9498
return nil
9599
}
@@ -105,6 +109,8 @@ func (ccr *ccResolverWrapper) UpdateState(s resolver.State) error {
105109
}
106110

107111
func (ccr *ccResolverWrapper) ReportError(err error) {
112+
ccr.incomingMu.Lock()
113+
defer ccr.incomingMu.Unlock()
108114
if ccr.done.HasFired() {
109115
return
110116
}
@@ -114,6 +120,8 @@ func (ccr *ccResolverWrapper) ReportError(err error) {
114120

115121
// NewAddress is called by the resolver implementation to send addresses to gRPC.
116122
func (ccr *ccResolverWrapper) NewAddress(addrs []resolver.Address) {
123+
ccr.incomingMu.Lock()
124+
defer ccr.incomingMu.Unlock()
117125
if ccr.done.HasFired() {
118126
return
119127
}
@@ -128,6 +136,8 @@ func (ccr *ccResolverWrapper) NewAddress(addrs []resolver.Address) {
128136
// NewServiceConfig is called by the resolver implementation to send service
129137
// configs to gRPC.
130138
func (ccr *ccResolverWrapper) NewServiceConfig(sc string) {
139+
ccr.incomingMu.Lock()
140+
defer ccr.incomingMu.Unlock()
131141
if ccr.done.HasFired() {
132142
return
133143
}

0 commit comments

Comments
 (0)