mirror of
https://github.com/golang/go
synced 2024-09-25 13:10:11 -06:00
net: fix race in (*resolverConfig).tryUpdate
Fixes #14072. Change-Id: Ie31caa06690ac621906fc5acd34da2efa4e2049f Reviewed-on: https://go-review.googlesource.com/18860 Reviewed-by: Mikio Hara <mikioh.mikioh@gmail.com> Run-TryBot: Mikio Hara <mikioh.mikioh@gmail.com>
This commit is contained in:
parent
315f4c70f1
commit
5efbdd9d10
@ -229,7 +229,6 @@ type resolverConfig struct {
|
||||
// time to recheck resolv.conf.
|
||||
ch chan struct{} // guards lastChecked and modTime
|
||||
lastChecked time.Time // last time resolv.conf was checked
|
||||
modTime time.Time // time of resolv.conf modification
|
||||
|
||||
mu sync.RWMutex // protects dnsConfig
|
||||
dnsConfig *dnsConfig // parsed resolv.conf structure used in lookups
|
||||
@ -239,16 +238,12 @@ var resolvConf resolverConfig
|
||||
|
||||
// init initializes conf and is only called via conf.initOnce.
|
||||
func (conf *resolverConfig) init() {
|
||||
// Set dnsConfig, modTime, and lastChecked so we don't parse
|
||||
// Set dnsConfig and lastChecked so we don't parse
|
||||
// resolv.conf twice the first time.
|
||||
conf.dnsConfig = systemConf().resolv
|
||||
if conf.dnsConfig == nil {
|
||||
conf.dnsConfig = dnsReadConfig("/etc/resolv.conf")
|
||||
}
|
||||
|
||||
if fi, err := os.Stat("/etc/resolv.conf"); err == nil {
|
||||
conf.modTime = fi.ModTime()
|
||||
}
|
||||
conf.lastChecked = time.Now()
|
||||
|
||||
// Prepare ch so that only one update of resolverConfig may
|
||||
@ -274,18 +269,13 @@ func (conf *resolverConfig) tryUpdate(name string) {
|
||||
}
|
||||
conf.lastChecked = now
|
||||
|
||||
var mtime time.Time
|
||||
if fi, err := os.Stat(name); err == nil {
|
||||
if fi.ModTime().Equal(conf.modTime) {
|
||||
return
|
||||
mtime = fi.ModTime()
|
||||
}
|
||||
conf.modTime = fi.ModTime()
|
||||
} else {
|
||||
// If modTime wasn't set prior, assume nothing has changed.
|
||||
if conf.modTime.IsZero() {
|
||||
if mtime.Equal(conf.dnsConfig.mtime) {
|
||||
return
|
||||
}
|
||||
conf.modTime = time.Time{}
|
||||
}
|
||||
|
||||
dnsConf := dnsReadConfig(name)
|
||||
conf.mu.Lock()
|
||||
|
@ -8,6 +8,8 @@
|
||||
|
||||
package net
|
||||
|
||||
import "time"
|
||||
|
||||
var defaultNS = []string{"127.0.0.1", "::1"}
|
||||
|
||||
type dnsConfig struct {
|
||||
@ -20,6 +22,7 @@ type dnsConfig struct {
|
||||
unknownOpt bool // anything unknown was encountered
|
||||
lookup []string // OpenBSD top-level database "lookup" order
|
||||
err error // any error that occurs during open of resolv.conf
|
||||
mtime time.Time // time of resolv.conf modification
|
||||
}
|
||||
|
||||
// See resolv.conf(5) on a Linux machine.
|
||||
@ -38,6 +41,13 @@ func dnsReadConfig(filename string) *dnsConfig {
|
||||
return conf
|
||||
}
|
||||
defer file.close()
|
||||
if fi, err := file.file.Stat(); err == nil {
|
||||
conf.mtime = fi.ModTime()
|
||||
} else {
|
||||
conf.servers = defaultNS
|
||||
conf.err = err
|
||||
return conf
|
||||
}
|
||||
for line, ok := file.readLine(); ok; line, ok = file.readLine() {
|
||||
if len(line) > 0 && (line[0] == ';' || line[0] == '#') {
|
||||
// comment.
|
||||
|
@ -10,6 +10,7 @@ import (
|
||||
"os"
|
||||
"reflect"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
var dnsReadConfigTests = []struct {
|
||||
@ -76,6 +77,7 @@ func TestDNSReadConfig(t *testing.T) {
|
||||
if conf.err != nil {
|
||||
t.Fatal(conf.err)
|
||||
}
|
||||
conf.mtime = time.Time{}
|
||||
if !reflect.DeepEqual(conf, tt.want) {
|
||||
t.Errorf("%s:\ngot: %+v\nwant: %+v", tt.name, conf, tt.want)
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user