mirror of
https://github.com/Control-D-Inc/ctrld.git
synced 2026-02-03 22:18:39 +00:00
cmd/cli: ensure goroutines that check DNS terminated
So changes to DNS after ctrld stopped won't be reverted by the goroutine itself. The problem happens rarely on darwin, because networksetup command won't propagate config to /etc/resolv.conf if there is no changes between multiple running.
This commit is contained in:
committed by
Cuong Manh Le
parent
62a0ba8731
commit
a007394f60
@@ -1333,6 +1333,10 @@ func run(appCallback *AppCallback, stopCh chan struct{}) {
|
||||
|
||||
close(waitCh)
|
||||
<-stopCh
|
||||
|
||||
// Wait goroutines which watches/manipulates DNS settings terminated,
|
||||
// ensuring that changes to DNS since here won't be reverted.
|
||||
p.dnsWg.Wait()
|
||||
for _, f := range p.onStopped {
|
||||
f()
|
||||
}
|
||||
|
||||
@@ -78,6 +78,7 @@ type prog struct {
|
||||
csSetDnsDone chan struct{}
|
||||
csSetDnsOk bool
|
||||
dnsWatchDogOnce sync.Once
|
||||
dnsWg sync.WaitGroup
|
||||
|
||||
cfg *ctrld.Config
|
||||
localUpstreams []string
|
||||
@@ -596,7 +597,11 @@ func (p *prog) setDNS() {
|
||||
for i := range nameservers {
|
||||
servers[i] = netip.MustParseAddr(nameservers[i])
|
||||
}
|
||||
go watchResolvConf(netIface, servers, setResolvConf)
|
||||
p.dnsWg.Add(1)
|
||||
go func() {
|
||||
defer p.dnsWg.Done()
|
||||
p.watchResolvConf(netIface, servers, setResolvConf)
|
||||
}()
|
||||
}
|
||||
if allIfaces {
|
||||
withEachPhysicalInterfaces(netIface.Name, "set DNS", func(i *net.Interface) error {
|
||||
@@ -604,7 +609,11 @@ func (p *prog) setDNS() {
|
||||
})
|
||||
}
|
||||
if p.dnsWatchdogEnabled() {
|
||||
go p.dnsWatchdog(netIface, nameservers, allIfaces)
|
||||
p.dnsWg.Add(1)
|
||||
go func() {
|
||||
defer p.dnsWg.Done()
|
||||
p.dnsWatchdog(netIface, nameservers, allIfaces)
|
||||
}()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -639,24 +648,30 @@ func (p *prog) dnsWatchdog(iface *net.Interface, nameservers []string, allIfaces
|
||||
slices.Sort(ns)
|
||||
ticker := time.NewTicker(p.dnsWatchdogDuration())
|
||||
logger := mainLog.Load().With().Str("iface", iface.Name).Logger()
|
||||
for range ticker.C {
|
||||
if dnsChanged(iface, ns) {
|
||||
logger.Debug().Msg("DNS settings were changed, re-applying settings")
|
||||
if err := setDNS(iface, ns); err != nil {
|
||||
mainLog.Load().Error().Err(err).Str("iface", iface.Name).Msgf("could not re-apply DNS settings")
|
||||
}
|
||||
}
|
||||
if allIfaces {
|
||||
withEachPhysicalInterfaces(iface.Name, "re-applying DNS", func(i *net.Interface) error {
|
||||
if dnsChanged(i, ns) {
|
||||
if err := setDnsIgnoreUnusableInterface(i, nameservers); err != nil {
|
||||
mainLog.Load().Error().Err(err).Str("iface", i.Name).Msgf("could not re-apply DNS settings")
|
||||
} else {
|
||||
mainLog.Load().Debug().Msgf("re-applying DNS for interface %q successfully", i.Name)
|
||||
}
|
||||
for {
|
||||
select {
|
||||
case <-p.stopCh:
|
||||
mainLog.Load().Debug().Msg("stop dns watchdog")
|
||||
return
|
||||
case <-ticker.C:
|
||||
if dnsChanged(iface, ns) {
|
||||
logger.Debug().Msg("DNS settings were changed, re-applying settings")
|
||||
if err := setDNS(iface, ns); err != nil {
|
||||
mainLog.Load().Error().Err(err).Str("iface", iface.Name).Msgf("could not re-apply DNS settings")
|
||||
}
|
||||
return nil
|
||||
})
|
||||
}
|
||||
if allIfaces {
|
||||
withEachPhysicalInterfaces(iface.Name, "re-applying DNS", func(i *net.Interface) error {
|
||||
if dnsChanged(i, ns) {
|
||||
if err := setDnsIgnoreUnusableInterface(i, nameservers); err != nil {
|
||||
mainLog.Load().Error().Err(err).Str("iface", i.Name).Msgf("could not re-apply DNS settings")
|
||||
} else {
|
||||
mainLog.Load().Debug().Msgf("re-applying DNS for interface %q successfully", i.Name)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
@@ -10,7 +10,7 @@ import (
|
||||
|
||||
// watchResolvConf watches any changes to /etc/resolv.conf file,
|
||||
// and reverting to the original config set by ctrld.
|
||||
func watchResolvConf(iface *net.Interface, ns []netip.Addr, setDnsFn func(iface *net.Interface, ns []netip.Addr) error) {
|
||||
func (p *prog) watchResolvConf(iface *net.Interface, ns []netip.Addr, setDnsFn func(iface *net.Interface, ns []netip.Addr) error) {
|
||||
resolvConfPath := "/etc/resolv.conf"
|
||||
// Evaluating symbolics link to watch the target file that /etc/resolv.conf point to.
|
||||
if rp, _ := filepath.EvalSymlinks(resolvConfPath); rp != "" {
|
||||
@@ -34,6 +34,9 @@ func watchResolvConf(iface *net.Interface, ns []netip.Addr, setDnsFn func(iface
|
||||
|
||||
for {
|
||||
select {
|
||||
case <-p.stopCh:
|
||||
mainLog.Load().Debug().Msgf("stopping watcher for %s", resolvConfPath)
|
||||
return
|
||||
case event, ok := <-watcher.Events:
|
||||
if !ok {
|
||||
return
|
||||
|
||||
Reference in New Issue
Block a user