Skip to content

Commit

Permalink
client: call .Endpoints() in dial() in client/v3/client.go instead of…
Browse files Browse the repository at this point in the history
… accessing cfg.Endpoints directly

https://github.com/etcd-io/etcd/blob/0cdd558361c6bdbbd9e4023558e2f6ece71c18ad/client/v3/client.go#L299 accesses
endpoints without acquiring lock. Fix it to call Endpoints()

Fix #13201
  • Loading branch information
yishuT committed Jul 27, 2021
1 parent 0cdd558 commit 77a5072
Showing 1 changed file with 14 additions and 10 deletions.
24 changes: 14 additions & 10 deletions client/v3/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,9 @@ type Client struct {
cfg Config
creds grpccredentials.TransportCredentials
resolver *resolver.EtcdManualResolver
mu *sync.RWMutex

epMu *sync.RWMutex
endpoints []string

ctx context.Context
cancel context.CancelFunc
Expand Down Expand Up @@ -160,18 +162,18 @@ func (c *Client) Ctx() context.Context { return c.ctx }
// Endpoints lists the registered endpoints for the client.
func (c *Client) Endpoints() []string {
// copy the slice; protect original endpoints from being changed
c.mu.RLock()
defer c.mu.RUnlock()
eps := make([]string, len(c.cfg.Endpoints))
copy(eps, c.cfg.Endpoints)
c.epMu.RLock()
defer c.epMu.RUnlock()
eps := make([]string, len(c.endpoints))
copy(eps, c.endpoints)
return eps
}

// SetEndpoints updates client's endpoints.
func (c *Client) SetEndpoints(eps ...string) {
c.mu.Lock()
defer c.mu.Unlock()
c.cfg.Endpoints = eps
c.epMu.Lock()
defer c.epMu.Unlock()
c.endpoints = eps

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

initialEndpoints := strings.Join(c.cfg.Endpoints, ";")
initialEndpoints := strings.Join(c.Endpoints(), ";")
target := fmt.Sprintf("%s://%p/#initially=[%s]", resolver.Schema, c, initialEndpoints)
conn, err := grpc.DialContext(dctx, target, opts...)
if err != nil {
Expand Down Expand Up @@ -344,7 +346,7 @@ func newClient(cfg *Config) (*Client, error) {
creds: creds,
ctx: ctx,
cancel: cancel,
mu: new(sync.RWMutex),
epMu: new(sync.RWMutex),
callOpts: defaultCallOpts,
lgMu: new(sync.RWMutex),
}
Expand Down Expand Up @@ -390,6 +392,8 @@ func newClient(cfg *Config) (*Client, error) {
client.cancel()
return nil, fmt.Errorf("at least one Endpoint is required in client config")
}
client.SetEndpoints(cfg.Endpoints...)

// Use a provided endpoint target so that for https:// without any tls config given, then
// grpc will assume the certificate server name is the endpoint host.
conn, err := client.dialWithBalancer()
Expand Down

0 comments on commit 77a5072

Please sign in to comment.