cmd/ctrld: only watch config when doing self-check

Avoiding reading/writing global config, causing a data race. While at
it, also guarding read/write access to cfg.Service.AllocateIP field,
since when it is read/write by multiple goroutines.
This commit is contained in:
Cuong Manh Le
2023-03-20 23:53:51 +07:00
committed by Cuong Manh Le
parent 8a56389396
commit f0c604a9f1
2 changed files with 27 additions and 7 deletions

View File

@@ -15,6 +15,7 @@ import (
"runtime"
"strconv"
"strings"
"sync"
"time"
"github.com/fsnotify/fsnotify"
@@ -508,13 +509,6 @@ func readConfigFile(writeDefaultConfig bool) bool {
if err == nil {
fmt.Println("loading config file from:", v.ConfigFileUsed())
defaultConfigFile = v.ConfigFileUsed()
v.OnConfigChange(func(in fsnotify.Event) {
if err := v.UnmarshalKey("listener", &cfg.Listener); err != nil {
log.Printf("failed to unmarshal listener config: %v", err)
return
}
})
v.WatchConfig()
return true
}
@@ -727,8 +721,26 @@ func selfCheckStatus(status service.Status) service.Status {
err := errors.New("query failed")
maxAttempts := 20
mainLog.Debug().Msg("Performing self-check")
var (
lcChanged map[string]*ctrld.ListenerConfig
mu sync.Mutex
)
v.OnConfigChange(func(in fsnotify.Event) {
mu.Lock()
defer mu.Unlock()
if err := v.UnmarshalKey("listener", &lcChanged); err != nil {
log.Printf("failed to unmarshal listener config: %v", err)
return
}
})
v.WatchConfig()
for i := 0; i < maxAttempts; i++ {
lc := cfg.Listener["0"]
mu.Lock()
if lcChanged != nil {
lc = lcChanged["0"]
}
mu.Unlock()
m := new(dns.Msg)
m.SetQuestion(selfCheckFQDN+".", dns.TypeA)
m.RecursionDesired = true

View File

@@ -28,6 +28,8 @@ var svcConfig = &service.Config{
}
type prog struct {
mu sync.Mutex
cfg *ctrld.Config
cache dnscache.Cacher
}
@@ -106,7 +108,9 @@ func (p *prog) run() {
} else {
mainLog.Info().Msg("writing config file to: " + defaultConfigFile)
}
p.mu.Lock()
p.cfg.Service.AllocateIP = true
p.mu.Unlock()
p.preRun()
mainLog.Info().Msgf("Starting DNS server on listener.%s: %s", listenerNum, net.JoinHostPort(ip, strconv.Itoa(port)))
if err := p.serveDNS(listenerNum); err != nil {
@@ -132,6 +136,8 @@ func (p *prog) Stop(s service.Service) error {
}
func (p *prog) allocateIP(ip string) error {
p.mu.Lock()
defer p.mu.Unlock()
if !p.cfg.Service.AllocateIP {
return nil
}
@@ -139,6 +145,8 @@ func (p *prog) allocateIP(ip string) error {
}
func (p *prog) deAllocateIP() error {
p.mu.Lock()
defer p.mu.Unlock()
if !p.cfg.Service.AllocateIP {
return nil
}