Skip to content

Commit

Permalink
Avoid race by using conditional deep copy
Browse files Browse the repository at this point in the history
Signed-off-by: Derek Collison <derek@nats.io>
  • Loading branch information
derekcollison committed Jun 22, 2018
1 parent 3f39c24 commit b7ece91
Show file tree
Hide file tree
Showing 3 changed files with 15 additions and 3 deletions.
2 changes: 1 addition & 1 deletion server/client.go
Expand Up @@ -908,7 +908,7 @@ func (c *client) processPing() {
// If there was a cluster update since this client was created,
// send an updated INFO protocol now.
if srv.lastCURLsUpdate >= c.start.UnixNano() {
c.sendInfo(c.generateClientInfoJSON(srv.info))
c.sendInfo(c.generateClientInfoJSON(srv.copyInfo()))
}
c.mu.Unlock()
srv.mu.Unlock()
Expand Down
2 changes: 1 addition & 1 deletion server/route.go
Expand Up @@ -389,7 +389,7 @@ func (s *Server) sendAsyncInfoToClients() {
if c.opts.Protocol >= ClientProtoInfo && c.flags.isSet(firstPongSent) {
// sendInfo takes care of checking if the connection is still
// valid or not, so don't duplicate tests here.
c.sendInfo(c.generateClientInfoJSON(s.info))
c.sendInfo(c.generateClientInfoJSON(s.copyInfo()))
}
c.mu.Unlock()
}
Expand Down
14 changes: 13 additions & 1 deletion server/server.go
Expand Up @@ -708,6 +708,18 @@ func (s *Server) HTTPHandler() http.Handler {
return s.httpHandler
}

// Perform a conditional deep copy due to reference nature of ClientConnectURLs.
// If updates are made to Info, this function should be consulted and updated.
// Assume lock is held.
func (s *Server) copyInfo() Info {
info := s.info
if info.ClientConnectURLs != nil {
info.ClientConnectURLs = make([]string, len(s.info.ClientConnectURLs))
copy(info.ClientConnectURLs, s.info.ClientConnectURLs)
}
return info
}

func (s *Server) createClient(conn net.Conn) *client {
// Snapshot server options.
opts := s.getOpts()
Expand All @@ -716,7 +728,7 @@ func (s *Server) createClient(conn net.Conn) *client {

// Grab JSON info string
s.mu.Lock()
info := s.info
info := s.copyInfo()
s.totalClients++
s.mu.Unlock()

Expand Down

0 comments on commit b7ece91

Please sign in to comment.