Pull request: data race
Merge in DNS/adguard-home from 2489-data-race to master
Closes #2489.
Squashed commit of the following:
commit 7745b79f0489970f3ba1bb11bb757b998fa6369c
Merge: d070cfd53 93ffed780
Author: Eugene Burkov <e.burkov@adguard.com>
Date: Mon Dec 28 19:00:07 2020 +0300
Merge branch 'master' into 2489-data-race
commit d070cfd53e72b609f305cd8d79d747fbf47dc5f4
Author: Eugene Burkov <e.burkov@adguard.com>
Date: Fri Dec 25 20:31:21 2020 +0300
util: fix ignoring write events bug
commit 725850bdbd96eaf65fb3228fcaeba51a3ec95905
Author: Eugene Burkov <e.burkov@adguard.com>
Date: Fri Dec 25 17:38:29 2020 +0300
util: simpl hosts upd algo
This commit is contained in:
parent
93ffed7809
commit
8a1d86aa7d
|
@ -29,10 +29,12 @@ type AutoHosts struct {
|
||||||
// TODO(a.garipov): Make better use of newtypes. Perhaps a custom map.
|
// TODO(a.garipov): Make better use of newtypes. Perhaps a custom map.
|
||||||
tableReverse map[string][]string
|
tableReverse map[string][]string
|
||||||
|
|
||||||
hostsFn string // path to the main hosts-file
|
hostsFn string // path to the main hosts-file
|
||||||
hostsDirs []string // paths to OS-specific directories with hosts-files
|
hostsDirs []string // paths to OS-specific directories with hosts-files
|
||||||
watcher *fsnotify.Watcher // file and directory watcher object
|
watcher *fsnotify.Watcher // file and directory watcher object
|
||||||
updateChan chan bool // signal for 'updateLoop' goroutine
|
|
||||||
|
// onlyWritesChan used to contain only writing events from watcher.
|
||||||
|
onlyWritesChan chan fsnotify.Event
|
||||||
|
|
||||||
onChanged onChangedT // notification to other modules
|
onChanged onChangedT // notification to other modules
|
||||||
}
|
}
|
||||||
|
@ -54,7 +56,7 @@ func (a *AutoHosts) notify() {
|
||||||
// hostsFn: Override default name for the hosts-file (optional)
|
// hostsFn: Override default name for the hosts-file (optional)
|
||||||
func (a *AutoHosts) Init(hostsFn string) {
|
func (a *AutoHosts) Init(hostsFn string) {
|
||||||
a.table = make(map[string][]net.IP)
|
a.table = make(map[string][]net.IP)
|
||||||
a.updateChan = make(chan bool, 2)
|
a.onlyWritesChan = make(chan fsnotify.Event, 2)
|
||||||
|
|
||||||
a.hostsFn = "/etc/hosts"
|
a.hostsFn = "/etc/hosts"
|
||||||
if runtime.GOOS == "windows" {
|
if runtime.GOOS == "windows" {
|
||||||
|
@ -82,8 +84,7 @@ func (a *AutoHosts) Init(hostsFn string) {
|
||||||
func (a *AutoHosts) Start() {
|
func (a *AutoHosts) Start() {
|
||||||
log.Debug("Start AutoHosts module")
|
log.Debug("Start AutoHosts module")
|
||||||
|
|
||||||
go a.updateLoop()
|
a.updateHosts()
|
||||||
a.updateChan <- true
|
|
||||||
|
|
||||||
if a.watcher != nil {
|
if a.watcher != nil {
|
||||||
go a.watcherLoop()
|
go a.watcherLoop()
|
||||||
|
@ -104,11 +105,10 @@ func (a *AutoHosts) Start() {
|
||||||
|
|
||||||
// Close - close module
|
// Close - close module
|
||||||
func (a *AutoHosts) Close() {
|
func (a *AutoHosts) Close() {
|
||||||
a.updateChan <- false
|
|
||||||
close(a.updateChan)
|
|
||||||
if a.watcher != nil {
|
if a.watcher != nil {
|
||||||
_ = a.watcher.Close()
|
_ = a.watcher.Close()
|
||||||
}
|
}
|
||||||
|
close(a.onlyWritesChan)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Process returns the list of IP addresses for the hostname or nil if nothing
|
// Process returns the list of IP addresses for the hostname or nil if nothing
|
||||||
|
@ -273,20 +273,32 @@ func (a *AutoHosts) load(table map[string][]net.IP, tableRev map[string][]string
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// onlyWrites is a filter for (*fsnotify.Watcher).Events.
|
||||||
|
func (a *AutoHosts) onlyWrites() {
|
||||||
|
for event := range a.watcher.Events {
|
||||||
|
if event.Op&fsnotify.Write == fsnotify.Write {
|
||||||
|
a.onlyWritesChan <- event
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Receive notifications from fsnotify package
|
// Receive notifications from fsnotify package
|
||||||
func (a *AutoHosts) watcherLoop() {
|
func (a *AutoHosts) watcherLoop() {
|
||||||
|
go a.onlyWrites()
|
||||||
for {
|
for {
|
||||||
select {
|
select {
|
||||||
case event, ok := <-a.watcher.Events:
|
case event, ok := <-a.onlyWritesChan:
|
||||||
if !ok {
|
if !ok {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Assume that we sometimes have the same event occurred
|
||||||
|
// several times.
|
||||||
repeat := true
|
repeat := true
|
||||||
for repeat {
|
for repeat {
|
||||||
select {
|
select {
|
||||||
case <-a.watcher.Events:
|
case _, ok = <-a.onlyWritesChan:
|
||||||
// Skip this duplicating event
|
repeat = ok
|
||||||
default:
|
default:
|
||||||
repeat = false
|
repeat = false
|
||||||
}
|
}
|
||||||
|
@ -294,12 +306,7 @@ func (a *AutoHosts) watcherLoop() {
|
||||||
|
|
||||||
if event.Op&fsnotify.Write == fsnotify.Write {
|
if event.Op&fsnotify.Write == fsnotify.Write {
|
||||||
log.Debug("AutoHosts: modified: %s", event.Name)
|
log.Debug("AutoHosts: modified: %s", event.Name)
|
||||||
select {
|
a.updateHosts()
|
||||||
case a.updateChan <- true:
|
|
||||||
// sent a signal to 'updateLoop' goroutine
|
|
||||||
default:
|
|
||||||
// queue is full
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
case err, ok := <-a.watcher.Errors:
|
case err, ok := <-a.watcher.Errors:
|
||||||
|
@ -311,18 +318,6 @@ func (a *AutoHosts) watcherLoop() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// updateLoop reads static hosts from system files.
|
|
||||||
func (a *AutoHosts) updateLoop() {
|
|
||||||
for ok := range a.updateChan {
|
|
||||||
if !ok {
|
|
||||||
log.Debug("Finished AutoHosts update loop")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
a.updateHosts()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// updateHosts - loads system hosts
|
// updateHosts - loads system hosts
|
||||||
func (a *AutoHosts) updateHosts() {
|
func (a *AutoHosts) updateHosts() {
|
||||||
table := make(map[string][]net.IP)
|
table := make(map[string][]net.IP)
|
||||||
|
|
Loading…
Reference in New Issue