cmd/cli: ensure set/reset DNS is done before checking OS resolver

Otherwise, new DNS settings could be reverted by dns watchers, causing
the checking will be always false.
This commit is contained in:
Cuong Manh Le
2025-01-14 14:33:15 +07:00
committed by Cuong Manh Le
parent 5db7d3577b
commit a95d50c0af
4 changed files with 21 additions and 8 deletions
+1 -1
View File
@@ -552,7 +552,7 @@ func (p *prog) proxy(ctx context.Context, req *proxyRequest) *proxyResponse {
continue continue
} }
if p.um.isDown(upstreams[n]) { if p.um.isDown(upstreams[n]) {
ctrld.Log(ctx, mainLog.Load().Warn(), "%s is down", upstreams[n]) ctrld.Log(ctx, mainLog.Load().Debug(), "%s is down", upstreams[n])
continue continue
} }
answer := resolve(n, upstreamConfig, req.msg) answer := resolve(n, upstreamConfig, req.msg)
+1 -1
View File
@@ -728,7 +728,7 @@ func (p *prog) dnsWatchdog(iface *net.Interface, nameservers []string, allIfaces
mainLog.Load().Debug().Msg("stop dns watchdog") mainLog.Load().Debug().Msg("stop dns watchdog")
return return
case <-ticker.C: case <-ticker.C:
if p.leakingQuery.Load() { if p.leakingQuery.Load() || p.um.isChecking(upstreamOS) {
return return
} }
if dnsChanged(iface, ns) { if dnsChanged(iface, ns) {
+1 -1
View File
@@ -40,7 +40,7 @@ func (p *prog) watchResolvConf(iface *net.Interface, ns []netip.Addr, setDnsFn f
mainLog.Load().Debug().Msgf("stopping watcher for %s", resolvConfPath) mainLog.Load().Debug().Msgf("stopping watcher for %s", resolvConfPath)
return return
case event, ok := <-watcher.Events: case event, ok := <-watcher.Events:
if p.leakingQuery.Load() { if p.leakingQuery.Load() || p.um.isChecking(upstreamOS) {
return return
} }
if !ok { if !ok {
+18 -5
View File
@@ -60,6 +60,14 @@ func (um *upstreamMonitor) isDown(upstream string) bool {
return um.down[upstream] return um.down[upstream]
} }
// isChecking reports whether the given upstream is being checked.
func (um *upstreamMonitor) isChecking(upstream string) bool {
um.mu.Lock()
defer um.mu.Unlock()
return um.checking[upstream]
}
// reset marks an upstream as up and set failed queries counter to zero. // reset marks an upstream as up and set failed queries counter to zero.
func (um *upstreamMonitor) reset(upstream string) { func (um *upstreamMonitor) reset(upstream string) {
um.mu.Lock() um.mu.Lock()
@@ -86,9 +94,10 @@ func (p *prog) checkUpstream(upstream string, uc *ctrld.UpstreamConfig) {
p.um.mu.Unlock() p.um.mu.Unlock()
}() }()
if uc.Type == ctrld.ResolverTypeOS { isOsResolver := uc.Type == ctrld.ResolverTypeOS
ns := ctrld.InitializeOsResolver() if isOsResolver {
mainLog.Load().Debug().Msgf("re-initializing OS resolver with nameservers: %v", ns) p.resetDNS()
defer p.setDNS()
} }
resolver, err := ctrld.NewResolver(uc) resolver, err := ctrld.NewResolver(uc)
if err != nil { if err != nil {
@@ -105,12 +114,16 @@ func (p *prog) checkUpstream(upstream string, uc *ctrld.UpstreamConfig) {
ctx, cancel := context.WithTimeout(context.Background(), timeout) ctx, cancel := context.WithTimeout(context.Background(), timeout)
defer cancel() defer cancel()
uc.ReBootstrap() uc.ReBootstrap()
if isOsResolver {
ctrld.InitializeOsResolver()
}
_, err := resolver.Resolve(ctx, msg) _, err := resolver.Resolve(ctx, msg)
return err return err
} }
mainLog.Load().Warn().Msgf("upstream %q is offline", uc.Endpoint)
for { for {
if err := check(); err == nil { if err := check(); err == nil {
mainLog.Load().Debug().Msgf("upstream %q is online", uc.Endpoint) mainLog.Load().Warn().Msgf("upstream %q is online", uc.Endpoint)
p.um.reset(upstream) p.um.reset(upstream)
if p.leakingQuery.CompareAndSwap(true, false) { if p.leakingQuery.CompareAndSwap(true, false) {
p.leakingQueryMu.Lock() p.leakingQueryMu.Lock()
@@ -120,7 +133,7 @@ func (p *prog) checkUpstream(upstream string, uc *ctrld.UpstreamConfig) {
} }
return return
} else { } else {
mainLog.Load().Debug().Msgf("upstream %q is offline: %v", uc.Endpoint, err) mainLog.Load().Debug().Msgf("checked upstream %q failed: %v", uc.Endpoint, err)
} }
time.Sleep(checkUpstreamBackoffSleep) time.Sleep(checkUpstreamBackoffSleep)
} }