Browse Source

Fix race referencing config

Three data races existed referencing the Config item - these
can be detected by running after building with 'go build -race'
on go 1.4.2. This fixes them by adding an RWMutex to protect
the config structure.
Alex Bligh 10 years ago
parent
commit
75f21937fb
4 changed files with 35 additions and 12 deletions
  1. 23 1
      config.go
  2. 2 2
      geodns.go
  3. 3 2
      geoip.go
  4. 7 7
      stathat.go

+ 23 - 1
config.go

@@ -4,6 +4,7 @@ import (
 	"fmt"
 	"log"
 	"os"
+	"sync"
 	"time"
 
 	"github.com/abh/geodns/Godeps/_workspace/src/code.google.com/p/gcfg"
@@ -23,6 +24,25 @@ type AppConfig struct {
 }
 
 var Config = new(AppConfig)
+var cfgMutex sync.RWMutex
+
+func (conf *AppConfig) HasStatHat() bool {
+	cfgMutex.RLock()
+	defer cfgMutex.RUnlock()
+	return conf.Flags.HasStatHat
+}
+
+func (conf *AppConfig) StatHatApiKey() string {
+	cfgMutex.RLock()
+	defer cfgMutex.RUnlock()
+	return conf.StatHat.ApiKey
+}
+
+func (conf *AppConfig) GeoIPDirectory() string {
+	cfgMutex.RLock()
+	defer cfgMutex.RUnlock()
+	return conf.GeoIP.Directory
+}
 
 func configWatcher(fileName string) {
 
@@ -91,7 +111,9 @@ func configReader(fileName string) error {
 	// log.Println("STATHAT APIKEY:", cfg.StatHat.ApiKey)
 	// log.Println("STATHAT FLAG  :", cfg.Flags.HasStatHat)
 
-	Config = cfg
+	cfgMutex.Lock()
+	*Config = *cfg // shallow copy to prevent race conditions in referring to Config.foo()
+	cfgMutex.Unlock()
 
 	return nil
 }

+ 2 - 2
geodns.go

@@ -141,8 +141,6 @@ func main() {
 	metrics := NewMetrics()
 	go metrics.Updater()
 
-	go statHatPoster()
-
 	if *flaginter == "*" {
 		addrs, _ := net.InterfaceAddrs()
 		ips := make([]string, 0)
@@ -161,6 +159,8 @@ func main() {
 
 	inter := getInterfaces()
 
+	go statHatPoster()
+
 	Zones := make(Zones)
 
 	go monitor(Zones)

+ 3 - 2
geoip.go

@@ -81,8 +81,9 @@ func (g *GeoIP) GetASN(ip net.IP) (asn string, netmask int) {
 }
 
 func (g *GeoIP) setDirectory() {
-	if len(Config.GeoIP.Directory) > 0 {
-		geoip.SetCustomDirectory(Config.GeoIP.Directory)
+	directory := Config.GeoIPDirectory()
+	if len(directory) > 0 {
+		geoip.SetCustomDirectory(directory)
 	}
 }
 

+ 7 - 7
stathat.go

@@ -12,7 +12,7 @@ import (
 
 func (zs *Zones) statHatPoster() {
 
-	if len(Config.StatHat.ApiKey) == 0 {
+	if !Config.HasStatHat() {
 		return
 	}
 
@@ -40,17 +40,17 @@ func (zs *Zones) statHatPoster() {
 
 				apiKey := zone.Logging.StatHatAPI
 				if len(apiKey) == 0 {
-					apiKey = Config.StatHat.ApiKey
+					apiKey = Config.StatHatApiKey()
 				}
 				if len(apiKey) == 0 {
 					continue
 				}
-				stathat.PostEZCount("zone "+name+" queries~"+suffix, Config.StatHat.ApiKey, int(newCount))
+				stathat.PostEZCount("zone "+name+" queries~"+suffix, Config.StatHatApiKey(), int(newCount))
 
 				ednsCount := zone.Metrics.EdnsQueries.Count()
 				newEdnsCount := ednsCount - lastEdnsCounts[name]
 				lastEdnsCounts[name] = ednsCount
-				stathat.PostEZCount("zone "+name+" edns queries~"+suffix, Config.StatHat.ApiKey, int(newEdnsCount))
+				stathat.PostEZCount("zone "+name+" edns queries~"+suffix, Config.StatHatApiKey(), int(newEdnsCount))
 
 			}
 		}
@@ -68,7 +68,7 @@ func statHatPoster() {
 	for {
 		time.Sleep(60 * time.Second)
 
-		if !Config.Flags.HasStatHat {
+		if !Config.HasStatHat() {
 			log.Println("No stathat configuration")
 			continue
 		}
@@ -79,8 +79,8 @@ func statHatPoster() {
 		newQueries := current - lastQueryCount
 		lastQueryCount = current
 
-		stathat.PostEZCount("queries~"+suffix, Config.StatHat.ApiKey, int(newQueries))
-		stathat.PostEZValue("goroutines "+serverID, Config.StatHat.ApiKey, float64(runtime.NumGoroutine()))
+		stathat.PostEZCount("queries~"+suffix, Config.StatHatApiKey(), int(newQueries))
+		stathat.PostEZValue("goroutines "+serverID, Config.StatHatApiKey(), float64(runtime.NumGoroutine()))
 
 	}
 }