diff --git a/field/arena_notifiers.go b/field/arena_notifiers.go index 82ff026..0ce0462 100644 --- a/field/arena_notifiers.go +++ b/field/arena_notifiers.go @@ -105,11 +105,16 @@ func (arena *Arena) generateAudienceDisplayModeMessage() interface{} { } func (arena *Arena) generateDisplayConfigurationMessage() interface{} { + // Make a copy of the map to avoid potential data races; otherwise the same map would get iterated through as it is + // serialized to JSON. + displaysCopy := make(map[string]*Display) displayUrls := make(map[string]string) for displayId, display := range arena.Displays { + displaysCopy[displayId] = display displayUrls[displayId] = display.ToUrl() } - return &DisplayConfigurationMessage{arena.Displays, displayUrls} + + return &DisplayConfigurationMessage{displaysCopy, displayUrls} } func (arena *Arena) generateLedModeMessage() interface{} { diff --git a/field/display.go b/field/display.go index b197410..9ddba2f 100644 --- a/field/display.go +++ b/field/display.go @@ -131,6 +131,9 @@ func (display *Display) ToUrl() string { // Returns an unused ID that can be used for a new display. func (arena *Arena) NextDisplayId() string { + displayRegistryMutex.Lock() + defer displayRegistryMutex.Unlock() + // Loop until we get an ID that isn't already used. This is inefficient if there is a large number of displays, but // that should never be the case. for {