fix data race

Since state.Checks() returns a shallow copy
its elements must not be modified. Copying
the elements in the handler does not guarantee
consistency since that list is guarded by a different
lock. Therefore, the only solution is to have state.Checks()
return a deep copy.
This commit is contained in:
Frank Schroeder 2017-09-26 13:42:10 +02:00
parent 1530f12f56
commit 94fbae4732
No known key found for this signature in database
GPG Key ID: 4D65C6EAEC87DECD
2 changed files with 6 additions and 3 deletions

View File

@ -152,6 +152,7 @@ func (s *HTTPServer) AgentChecks(resp http.ResponseWriter, req *http.Request) (i
} }
// Use empty list instead of nil // Use empty list instead of nil
// checks needs to be a deep copy for this not be racy
for _, c := range checks { for _, c := range checks {
if c.ServiceTags == nil { if c.ServiceTags == nil {
c.ServiceTags = make([]string, 0) c.ServiceTags = make([]string, 0)

View File

@ -341,12 +341,14 @@ func (l *localState) UpdateCheck(checkID types.CheckID, status, output string) {
// Checks returns the locally registered checks that the // Checks returns the locally registered checks that the
// agent is aware of and are being kept in sync with the server // agent is aware of and are being kept in sync with the server
func (l *localState) Checks() map[types.CheckID]*structs.HealthCheck { func (l *localState) Checks() map[types.CheckID]*structs.HealthCheck {
checks := make(map[types.CheckID]*structs.HealthCheck)
l.RLock() l.RLock()
defer l.RUnlock() defer l.RUnlock()
for checkID, check := range l.checks { checks := make(map[types.CheckID]*structs.HealthCheck)
checks[checkID] = check for id, c := range l.checks {
c2 := new(structs.HealthCheck)
*c2 = *c
checks[id] = c2
} }
return checks return checks
} }