"os"
"runtime"
"sync"
+ "sync/atomic"
"time"
"golang.org/x/net/dns/dnsmessage"
ch chan struct{} // guards lastChecked and modTime
lastChecked time.Time // last time resolv.conf was checked
- mu sync.RWMutex // protects dnsConfig
- dnsConfig *dnsConfig // parsed resolv.conf structure used in lookups
+ dnsConfig atomic.Pointer[dnsConfig] // parsed resolv.conf structure used in lookups
}
var resolvConf resolverConfig
func getSystemDNSConfig() *dnsConfig {
resolvConf.tryUpdate("/etc/resolv.conf")
- resolvConf.mu.RLock()
- resolv := resolvConf.dnsConfig
- resolvConf.mu.RUnlock()
- return resolv
+ return resolvConf.dnsConfig.Load()
}
// init initializes conf and is only called via conf.initOnce.
func (conf *resolverConfig) init() {
// Set dnsConfig and lastChecked so we don't parse
// resolv.conf twice the first time.
- conf.dnsConfig = dnsReadConfig("/etc/resolv.conf")
+ conf.dnsConfig.Store(dnsReadConfig("/etc/resolv.conf"))
conf.lastChecked = time.Now()
// Prepare ch so that only one update of resolverConfig may
func (conf *resolverConfig) tryUpdate(name string) {
conf.initOnce.Do(conf.init)
- if conf.dnsConfig.noReload {
+ if conf.dnsConfig.Load().noReload {
return
}
if fi, err := os.Stat(name); err == nil {
mtime = fi.ModTime()
}
- if mtime.Equal(conf.dnsConfig.mtime) {
+ if mtime.Equal(conf.dnsConfig.Load().mtime) {
return
}
}
dnsConf := dnsReadConfig(name)
- conf.mu.Lock()
- conf.dnsConfig = dnsConf
- conf.mu.Unlock()
+ conf.dnsConfig.Store(dnsConf)
}
func (conf *resolverConfig) tryAcquireSema() bool {
}
func (conf *resolvConfTest) forceUpdateConf(c *dnsConfig, lastChecked time.Time) bool {
- conf.mu.Lock()
- conf.dnsConfig = c
- conf.mu.Unlock()
+ conf.dnsConfig.Store(c)
for i := 0; i < 5; i++ {
if conf.tryAcquireSema() {
conf.lastChecked = lastChecked
}
func (conf *resolvConfTest) servers() []string {
- conf.mu.RLock()
- servers := conf.dnsConfig.servers
- conf.mu.RUnlock()
- return servers
+ return conf.dnsConfig.Load().servers
}
func (conf *resolvConfTest) teardown() error {
func lookupWithFake(fake fakeDNSServer, name string, typ dnsmessage.Type) error {
r := Resolver{PreferGo: true, Dial: fake.DialContext}
- resolvConf.mu.RLock()
- conf := resolvConf.dnsConfig
- resolvConf.mu.RUnlock()
+ conf := resolvConf.dnsConfig.Load()
ctx, cancel := context.WithCancel(context.Background())
defer cancel()