Skip to content

Commit 4cbb949

Browse files
authored
Merge pull request #13203 from yishuT/client-race
client: call .Endpoints() in dial() in client/v3/client.go instead of accessing cfg.Endpoints directly
2 parents 9182a3c + 77a5072 commit 4cbb949

File tree

1 file changed

+14
-10
lines changed

1 file changed

+14
-10
lines changed

client/v3/client.go

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,9 @@ type Client struct {
5454
cfg Config
5555
creds grpccredentials.TransportCredentials
5656
resolver *resolver.EtcdManualResolver
57-
mu *sync.RWMutex
57+
58+
epMu *sync.RWMutex
59+
endpoints []string
5860

5961
ctx context.Context
6062
cancel context.CancelFunc
@@ -160,18 +162,18 @@ func (c *Client) Ctx() context.Context { return c.ctx }
160162
// Endpoints lists the registered endpoints for the client.
161163
func (c *Client) Endpoints() []string {
162164
// copy the slice; protect original endpoints from being changed
163-
c.mu.RLock()
164-
defer c.mu.RUnlock()
165-
eps := make([]string, len(c.cfg.Endpoints))
166-
copy(eps, c.cfg.Endpoints)
165+
c.epMu.RLock()
166+
defer c.epMu.RUnlock()
167+
eps := make([]string, len(c.endpoints))
168+
copy(eps, c.endpoints)
167169
return eps
168170
}
169171

170172
// SetEndpoints updates client's endpoints.
171173
func (c *Client) SetEndpoints(eps ...string) {
172-
c.mu.Lock()
173-
defer c.mu.Unlock()
174-
c.cfg.Endpoints = eps
174+
c.epMu.Lock()
175+
defer c.epMu.Unlock()
176+
c.endpoints = eps
175177

176178
c.resolver.SetEndpoints(eps)
177179
}
@@ -296,7 +298,7 @@ func (c *Client) dial(creds grpccredentials.TransportCredentials, dopts ...grpc.
296298
defer cancel() // TODO: Is this right for cases where grpc.WithBlock() is not set on the dial options?
297299
}
298300

299-
initialEndpoints := strings.Join(c.cfg.Endpoints, ";")
301+
initialEndpoints := strings.Join(c.Endpoints(), ";")
300302
target := fmt.Sprintf("%s://%p/#initially=[%s]", resolver.Schema, c, initialEndpoints)
301303
conn, err := grpc.DialContext(dctx, target, opts...)
302304
if err != nil {
@@ -344,7 +346,7 @@ func newClient(cfg *Config) (*Client, error) {
344346
creds: creds,
345347
ctx: ctx,
346348
cancel: cancel,
347-
mu: new(sync.RWMutex),
349+
epMu: new(sync.RWMutex),
348350
callOpts: defaultCallOpts,
349351
lgMu: new(sync.RWMutex),
350352
}
@@ -390,6 +392,8 @@ func newClient(cfg *Config) (*Client, error) {
390392
client.cancel()
391393
return nil, fmt.Errorf("at least one Endpoint is required in client config")
392394
}
395+
client.SetEndpoints(cfg.Endpoints...)
396+
393397
// Use a provided endpoint target so that for https:// without any tls config given, then
394398
// grpc will assume the certificate server name is the endpoint host.
395399
conn, err := client.dialWithBalancer()

0 commit comments

Comments
 (0)