@@ -160,6 +160,7 @@ func DialContext(ctx context.Context, target string, opts ...DialOption) (conn *
160160 cc .ctx , cc .cancel = context .WithCancel (context .Background ())
161161 cc .exitIdleCond = sync .NewCond (& cc .mu )
162162
163+ // Apply dial options.
163164 disableGlobalOpts := false
164165 for _ , opt := range opts {
165166 if _ , ok := opt .(* disableGlobalDialOptions ); ok {
@@ -177,21 +178,9 @@ func DialContext(ctx context.Context, target string, opts ...DialOption) (conn *
177178 for _ , opt := range opts {
178179 opt .apply (& cc .dopts )
179180 }
180-
181181 chainUnaryClientInterceptors (cc )
182182 chainStreamClientInterceptors (cc )
183183
184- defer func () {
185- if err != nil {
186- cc .Close ()
187- }
188- }()
189-
190- // Register ClientConn with channelz.
191- cc .channelzRegistration (target )
192-
193- cc .csMgr = newConnectivityStateManager (cc .ctx , cc .channelzID )
194-
195184 if err := cc .validateTransportCredentials (); err != nil {
196185 return nil , err
197186 }
@@ -211,6 +200,37 @@ func DialContext(ctx context.Context, target string, opts ...DialOption) (conn *
211200 cc .dopts .copts .UserAgent = grpcUA
212201 }
213202
203+ // Register ClientConn with channelz.
204+ cc .channelzRegistration (target )
205+
206+ // Determine the resolver to use.
207+ if err := cc .parseTargetAndFindResolver (); err != nil {
208+ channelz .RemoveEntry (cc .channelzID )
209+ return nil , err
210+ }
211+ if err = cc .determineAuthority (); err != nil {
212+ channelz .RemoveEntry (cc .channelzID )
213+ return nil , err
214+ }
215+
216+ cc .csMgr = newConnectivityStateManager (cc .ctx , cc .channelzID )
217+ cc .pickerWrapper = newPickerWrapper (cc .dopts .copts .StatsHandlers )
218+ cc .balancerWrapper = newCCBalancerWrapper (cc , balancer.BuildOptions {
219+ DialCreds : cc .dopts .copts .TransportCredentials ,
220+ CredsBundle : cc .dopts .copts .CredsBundle ,
221+ Dialer : cc .dopts .copts .Dialer ,
222+ Authority : cc .authority ,
223+ CustomUserAgent : cc .dopts .copts .UserAgent ,
224+ ChannelzParentID : cc .channelzID ,
225+ Target : cc .parsedTarget ,
226+ })
227+
228+ defer func () {
229+ if err != nil {
230+ cc .Close ()
231+ }
232+ }()
233+
214234 if cc .dopts .timeout > 0 {
215235 var cancel context.CancelFunc
216236 ctx , cancel = context .WithTimeout (ctx , cc .dopts .timeout )
@@ -235,14 +255,6 @@ func DialContext(ctx context.Context, target string, opts ...DialOption) (conn *
235255 cc .dopts .bs = backoff .DefaultExponential
236256 }
237257
238- // Determine the resolver to use.
239- if err := cc .parseTargetAndFindResolver (); err != nil {
240- return nil , err
241- }
242- if err = cc .determineAuthority (); err != nil {
243- return nil , err
244- }
245-
246258 if cc .dopts .scChan != nil {
247259 // Blocking wait for the initial service config.
248260 select {
@@ -359,31 +371,13 @@ func (cc *ClientConn) exitIdleMode() error {
359371 }()
360372
361373 cc .idlenessState = ccIdlenessStateExitingIdle
362- exitedIdle := false
363- if cc .blockingpicker == nil {
364- cc .blockingpicker = newPickerWrapper (cc .dopts .copts .StatsHandlers )
365- } else {
366- cc .blockingpicker .exitIdleMode ()
367- exitedIdle = true
368- }
374+ cc .pickerWrapper .exitIdleMode ()
369375
370376 var credsClone credentials.TransportCredentials
371377 if creds := cc .dopts .copts .TransportCredentials ; creds != nil {
372378 credsClone = creds .Clone ()
373379 }
374- if cc .balancerWrapper == nil {
375- cc .balancerWrapper = newCCBalancerWrapper (cc , balancer.BuildOptions {
376- DialCreds : credsClone ,
377- CredsBundle : cc .dopts .copts .CredsBundle ,
378- Dialer : cc .dopts .copts .Dialer ,
379- Authority : cc .authority ,
380- CustomUserAgent : cc .dopts .copts .UserAgent ,
381- ChannelzParentID : cc .channelzID ,
382- Target : cc .parsedTarget ,
383- })
384- } else {
385- cc .balancerWrapper .exitIdleMode ()
386- }
380+ cc .balancerWrapper .exitIdleMode ()
387381 cc .firstResolveEvent = grpcsync .NewEvent ()
388382 cc .mu .Unlock ()
389383
@@ -394,9 +388,7 @@ func (cc *ClientConn) exitIdleMode() error {
394388 return err
395389 }
396390
397- if exitedIdle {
398- cc .addTraceEvent ("exiting idle mode" )
399- }
391+ cc .addTraceEvent ("exiting idle mode" )
400392 return nil
401393}
402394
@@ -427,7 +419,7 @@ func (cc *ClientConn) enterIdleMode() error {
427419 // `cc.resolverWrapper`, it makes the code simpler in the wrapper. We should
428420 // try to do the same for the balancer and picker wrappers too.
429421 cc .resolverWrapper .close ()
430- cc .blockingpicker .enterIdleMode ()
422+ cc .pickerWrapper .enterIdleMode ()
431423 cc .balancerWrapper .enterIdleMode ()
432424 cc .csMgr .updateState (connectivity .Idle )
433425 cc .idlenessState = ccIdlenessStateIdle
@@ -655,7 +647,7 @@ type ClientConn struct {
655647 // The following provide their own synchronization, and therefore don't
656648 // require cc.mu to be held to access them.
657649 csMgr * connectivityStateManager
658- blockingpicker * pickerWrapper
650+ pickerWrapper * pickerWrapper
659651 safeConfigSelector iresolver.SafeConfigSelector
660652 czData * channelzData
661653 retryThrottler atomic.Value // Updated from service config.
@@ -910,7 +902,7 @@ func (cc *ClientConn) applyFailingLB(sc *serviceconfig.ParseResult) {
910902 err = status .Errorf (codes .Unavailable , "illegal service config type: %T" , sc .Config )
911903 }
912904 cc .safeConfigSelector .UpdateConfigSelector (& defaultConfigSelector {nil })
913- cc .blockingpicker .updatePicker (base .NewErrPicker (err ))
905+ cc .pickerWrapper .updatePicker (base .NewErrPicker (err ))
914906 cc .csMgr .updateState (connectivity .TransientFailure )
915907}
916908
@@ -1174,7 +1166,7 @@ func (cc *ClientConn) healthCheckConfig() *healthCheckConfig {
11741166}
11751167
11761168func (cc * ClientConn ) getTransport (ctx context.Context , failfast bool , method string ) (transport.ClientTransport , balancer.PickResult , error ) {
1177- return cc .blockingpicker .pick (ctx , failfast , balancer.PickInfo {
1169+ return cc .pickerWrapper .pick (ctx , failfast , balancer.PickInfo {
11781170 Ctx : ctx ,
11791171 FullMethodName : method ,
11801172 })
@@ -1267,24 +1259,18 @@ func (cc *ClientConn) Close() error {
12671259 cc .conns = nil
12681260 cc .csMgr .updateState (connectivity .Shutdown )
12691261
1270- pWrapper := cc .blockingpicker
1271- rWrapper := cc .resolverWrapper
1272- bWrapper := cc .balancerWrapper
1273- idlenessMgr := cc .idlenessMgr
1262+ // We can safely unlock and continue to access all fields now as
1263+ // cc.conns==nil, preventing any further operations on cc.
12741264 cc .mu .Unlock ()
12751265
12761266 // The order of closing matters here since the balancer wrapper assumes the
12771267 // picker is closed before it is closed.
1278- if pWrapper != nil {
1279- pWrapper .close ()
1280- }
1281- if bWrapper != nil {
1282- bWrapper .close ()
1283- }
1284- if rWrapper != nil {
1268+ cc .pickerWrapper .close ()
1269+ cc .balancerWrapper .close ()
1270+ if rWrapper := cc .resolverWrapper ; rWrapper != nil {
12851271 rWrapper .close ()
12861272 }
1287- if idlenessMgr != nil {
1273+ if idlenessMgr := cc . idlenessMgr ; idlenessMgr != nil {
12881274 idlenessMgr .Close ()
12891275 }
12901276
0 commit comments