mirror of
https://github.com/AdguardTeam/AdGuardHome.git
synced 2026-08-03 22:41:25 +00:00
Pull request 2728: AGDNS-4289-rm-global-context-etc-hosts
Squashed commit of the following: commit 0f8fa0222cf4896edcb369a40012a1aec0fb725a Merge:18d615e13f115af2f6Author: f.setrakov <f.setrakov@adguard.com> Date: Thu Jul 30 15:28:58 2026 +0300 Merge branch 'master' into AGDNS-4289-rm-global-context-etc-hosts commit18d615e13fAuthor: f.setrakov <f.setrakov@adguard.com> Date: Tue Jul 28 18:51:37 2026 +0300 home: imp code commite0e1768df0Author: f.setrakov <f.setrakov@adguard.com> Date: Tue Jul 28 17:12:41 2026 +0300 home: fix panic, imp code commite8028e5162Merge:2d4d93f918e56afa92Author: f.setrakov <f.setrakov@adguard.com> Date: Tue Jul 28 14:18:31 2026 +0300 Merge branch 'master' into AGDNS-4289-rm-global-context-etc-hosts commit2d4d93f912Author: f.setrakov <f.setrakov@adguard.com> Date: Tue Jul 28 13:55:04 2026 +0300 home: imp code commit64fc6ced97Author: f.setrakov <f.setrakov@adguard.com> Date: Fri Jul 24 10:54:46 2026 +0300 home: imp code commit790084a3e6Author: f.setrakov <f.setrakov@adguard.com> Date: Tue Jul 21 18:50:51 2026 +0300 home: rm etc hosts from global context
This commit is contained in:
parent
f115af2f65
commit
66360530c3
7 changed files with 186 additions and 131 deletions
|
|
@ -536,6 +536,7 @@ func (web *webAPI) finalizeInstall(
|
|||
web.confModifier,
|
||||
web.httpReg,
|
||||
web.conf.workDir,
|
||||
web.hostsContainer,
|
||||
)
|
||||
if err != nil {
|
||||
aghhttp.ErrorAndLog(ctx, l, r, w, http.StatusInternalServerError, "%s", err)
|
||||
|
|
@ -641,13 +642,14 @@ func startMods(
|
|||
confModifier agh.ConfigModifier,
|
||||
httpReg aghhttp.Registrar,
|
||||
workDir string,
|
||||
hc *aghnet.HostsContainer,
|
||||
) (err error) {
|
||||
statsDir, querylogDir, err := checkStatsAndQuerylogDirs(config, workDir)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = initDNS(ctx, baseLogger, tlsMgr, confModifier, httpReg, statsDir, querylogDir)
|
||||
err = initDNS(ctx, baseLogger, tlsMgr, confModifier, httpReg, statsDir, querylogDir, hc)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
|
|||
|
|
@ -165,14 +165,7 @@ func (web *webAPI) handleUpdate(w http.ResponseWriter, r *http.Request) {
|
|||
// The background context is used because the underlying functions wrap it
|
||||
// with timeout and shut down the server, which handles current request. It
|
||||
// also should be done in a separate goroutine for the same reason.
|
||||
go finishUpdate(
|
||||
context.Background(),
|
||||
web.logger,
|
||||
web.cmdCons,
|
||||
execPath,
|
||||
web.pidFilePath,
|
||||
web.conf.runningAsService,
|
||||
)
|
||||
go web.finishUpdate(context.Background(), execPath)
|
||||
}
|
||||
|
||||
// versionResponse is the response for /control/version.json endpoint.
|
||||
|
|
@ -221,47 +214,40 @@ func tlsConfUsesPrivilegedPorts(c *tlsConfigSettings) (ok bool) {
|
|||
}
|
||||
|
||||
// finishUpdate completes an update procedure. It is intended to be used as a
|
||||
// goroutine. l and cmdCons must not be nil.
|
||||
func finishUpdate(
|
||||
// goroutine.
|
||||
func (web *webAPI) finishUpdate(
|
||||
ctx context.Context,
|
||||
l *slog.Logger,
|
||||
cmdCons executil.CommandConstructor,
|
||||
execPath string,
|
||||
pidFilePath string,
|
||||
runningAsService bool,
|
||||
) {
|
||||
defer slogutil.RecoverAndExit(ctx, l, osutil.ExitCodeFailure)
|
||||
defer slogutil.RecoverAndExit(ctx, web.logger, osutil.ExitCodeFailure)
|
||||
|
||||
l.InfoContext(ctx, "stopping all tasks")
|
||||
web.logger.InfoContext(ctx, "stopping all tasks")
|
||||
|
||||
cleanup(ctx, l)
|
||||
cleanupAlways(ctx, l, pidFilePath)
|
||||
cleanup(ctx, web.logger, web.hostsContainer)
|
||||
cleanupAlways(ctx, web.logger, web.pidFilePath)
|
||||
|
||||
if runtime.GOOS == "windows" {
|
||||
finalizeWindowsUpdate(ctx, l, cmdCons, execPath, runningAsService)
|
||||
web.finalizeWindowsUpdate(ctx, execPath)
|
||||
|
||||
os.Exit(osutil.ExitCodeSuccess)
|
||||
}
|
||||
|
||||
var err error
|
||||
l.InfoContext(ctx, "restarting", "exec_path", execPath, "args", os.Args[1:])
|
||||
web.logger.InfoContext(ctx, "restarting", "exec_path", execPath, "args", os.Args[1:])
|
||||
err = syscall.Exec(execPath, os.Args, os.Environ())
|
||||
if err != nil {
|
||||
panic(fmt.Errorf("restarting: %w", err))
|
||||
}
|
||||
}
|
||||
|
||||
// finalizeWindowsUpdate completes an update procedure on windows. l and
|
||||
// cmdCons must not be nil.
|
||||
func finalizeWindowsUpdate(ctx context.Context,
|
||||
l *slog.Logger,
|
||||
cmdCons executil.CommandConstructor,
|
||||
// finalizeWindowsUpdate completes an update procedure on windows.
|
||||
func (web *webAPI) finalizeWindowsUpdate(
|
||||
ctx context.Context,
|
||||
execPath string,
|
||||
runningAsService bool,
|
||||
) {
|
||||
var commandConf *executil.CommandConfig
|
||||
|
||||
if runningAsService {
|
||||
if web.conf.runningAsService {
|
||||
// NOTE: We can't restart the service via "kardianos/service" package,
|
||||
// because it kills the process first we can't start a new instance,
|
||||
// because Windows doesn't allow it.
|
||||
|
|
@ -281,10 +267,10 @@ func finalizeWindowsUpdate(ctx context.Context,
|
|||
}
|
||||
}
|
||||
|
||||
l.InfoContext(ctx, "restarting", "exec_path", execPath, "args", os.Args[1:])
|
||||
web.logger.InfoContext(ctx, "restarting", "exec_path", execPath, "args", os.Args[1:])
|
||||
|
||||
var cmd executil.Command
|
||||
cmd, err := cmdCons.New(ctx, commandConf)
|
||||
cmd, err := web.cmdCons.New(ctx, commandConf)
|
||||
if err != nil {
|
||||
panic(fmt.Errorf("constructing cmd: %w", err))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -51,6 +51,7 @@ func initDNS(
|
|||
httpReg aghhttp.Registrar,
|
||||
statsDir string,
|
||||
querylogDir string,
|
||||
hc *aghnet.HostsContainer,
|
||||
) (err error) {
|
||||
anonymizer := config.anonymizer()
|
||||
|
||||
|
|
@ -108,14 +109,21 @@ func initDNS(
|
|||
|
||||
err = initDNSServer(
|
||||
ctx,
|
||||
globalContext.filters,
|
||||
globalContext.stats,
|
||||
globalContext.queryLog,
|
||||
globalContext.dhcpServer,
|
||||
anonymizer,
|
||||
baseLogger,
|
||||
dnsforward.DNSCreateParams{
|
||||
Logger: baseLogger,
|
||||
DNSFilter: globalContext.filters,
|
||||
Stats: globalContext.stats,
|
||||
QueryLog: globalContext.queryLog,
|
||||
PrivateNets: parseSubnetSet(config.DNS.PrivateNets),
|
||||
Anonymizer: anonymizer,
|
||||
DHCPServer: globalContext.dhcpServer,
|
||||
EtcHosts: hc,
|
||||
LocalDomain: config.DHCP.LocalDomainName,
|
||||
TLSConfigProvider: tlsMgr,
|
||||
},
|
||||
httpReg,
|
||||
tlsMgr,
|
||||
baseLogger,
|
||||
confModifier,
|
||||
)
|
||||
if err != nil {
|
||||
|
|
@ -127,36 +135,19 @@ func initDNS(
|
|||
return nil
|
||||
}
|
||||
|
||||
// initDNSServer initializes the [context.dnsServer]. To only use the internal
|
||||
// proxy, none of the arguments are required, but tlsMgr and l still must not be
|
||||
// nil, in other cases all the arguments also must not be nil. It also must not
|
||||
// be called unless [config] and [globalContext] are initialized.
|
||||
//
|
||||
// TODO(e.burkov): Use [dnsforward.DNSCreateParams] as a parameter.
|
||||
// initDNSServer initializes the [context.dnsServer]. tlsMgr and l must not be
|
||||
// nil. Other arguments, including params fields, are allowed to be nil if you
|
||||
// want to use only the internal proxy. It also must not be called unless
|
||||
// [config] and [globalContext] are initialized.
|
||||
func initDNSServer(
|
||||
ctx context.Context,
|
||||
filters *filtering.DNSFilter,
|
||||
sts stats.Interface,
|
||||
qlog querylog.QueryLog,
|
||||
dhcpSrv dnsforward.DHCP,
|
||||
anonymizer *aghnet.IPMut,
|
||||
l *slog.Logger,
|
||||
params dnsforward.DNSCreateParams,
|
||||
httpReg aghhttp.Registrar,
|
||||
tlsMgr *tlsManager,
|
||||
l *slog.Logger,
|
||||
confModifier agh.ConfigModifier,
|
||||
) (err error) {
|
||||
globalContext.dnsServer, err = dnsforward.NewServer(dnsforward.DNSCreateParams{
|
||||
Logger: l,
|
||||
DNSFilter: filters,
|
||||
Stats: sts,
|
||||
QueryLog: qlog,
|
||||
PrivateNets: parseSubnetSet(config.DNS.PrivateNets),
|
||||
Anonymizer: anonymizer,
|
||||
DHCPServer: dhcpSrv,
|
||||
EtcHosts: globalContext.etcHosts,
|
||||
LocalDomain: config.DHCP.LocalDomainName,
|
||||
TLSConfigProvider: tlsMgr,
|
||||
})
|
||||
globalContext.dnsServer, err = dnsforward.NewServer(params)
|
||||
defer func() {
|
||||
if err != nil {
|
||||
closeDNSServer(ctx)
|
||||
|
|
|
|||
|
|
@ -46,6 +46,7 @@ import (
|
|||
"github.com/AdguardTeam/golibs/netutil/urlutil"
|
||||
"github.com/AdguardTeam/golibs/osutil"
|
||||
"github.com/AdguardTeam/golibs/osutil/executil"
|
||||
"github.com/AdguardTeam/golibs/service"
|
||||
)
|
||||
|
||||
// Global context
|
||||
|
|
@ -62,10 +63,6 @@ type homeContext struct {
|
|||
filters *filtering.DNSFilter // DNS filtering module
|
||||
web *webAPI // Web (HTTP, HTTPS) module
|
||||
|
||||
// etcHosts contains IP-hostname mappings taken from the OS-specific hosts
|
||||
// configuration files, for example /etc/hosts.
|
||||
etcHosts *aghnet.HostsContainer
|
||||
|
||||
controlLock sync.Mutex
|
||||
}
|
||||
|
||||
|
|
@ -128,23 +125,27 @@ func Main(clientBuildFS fs.FS) {
|
|||
|
||||
pidFilePath := setPIDFilePath(opts)
|
||||
|
||||
var (
|
||||
hc *aghnet.HostsContainer
|
||||
hcWatcher service.Interface = service.Empty{}
|
||||
)
|
||||
if !opts.noEtcHosts {
|
||||
hc, hcWatcher, err = newHostsContainer(ctx, baseLogger)
|
||||
fatalOnError(err)
|
||||
}
|
||||
|
||||
sigHdlrLogger := baseLogger.With(slogutil.KeyPrefix, "signalhdlr")
|
||||
sigHdlr := newSignalHandler(sigHdlrLogger, signals, func(ctx context.Context) {
|
||||
defer close(done)
|
||||
sigHdlrCleanup := &signalHandlerCleanup{
|
||||
logger: sigHdlrLogger,
|
||||
hostsContainer: hc,
|
||||
glTokenFileRoot: glTokenFileRoot,
|
||||
hcWatcher: hcWatcher,
|
||||
done: done,
|
||||
pidFilePath: pidFilePath,
|
||||
glinetMode: opts.glinetMode,
|
||||
}
|
||||
|
||||
cleanup(ctx, sigHdlrLogger)
|
||||
cleanupAlways(ctx, sigHdlrLogger, pidFilePath)
|
||||
|
||||
if !opts.glinetMode {
|
||||
return
|
||||
}
|
||||
|
||||
closeErr := glTokenFileRoot.Close()
|
||||
if closeErr != nil {
|
||||
baseLogger.ErrorContext(ctx, "closing glinet token root", slogutil.KeyError, closeErr)
|
||||
os.Exit(osutil.ExitCodeFailure)
|
||||
}
|
||||
})
|
||||
sigHdlr := newSignalHandler(sigHdlrLogger, signals, sigHdlrCleanup.cleanup)
|
||||
|
||||
go sigHdlr.handle(ctx)
|
||||
|
||||
|
|
@ -163,6 +164,7 @@ func Main(clientBuildFS fs.FS) {
|
|||
workDir,
|
||||
confPath,
|
||||
pidFilePath,
|
||||
hc,
|
||||
)
|
||||
if err != nil {
|
||||
svcLogger.ErrorContext(ctx, "action failed", slogutil.KeyError, err)
|
||||
|
|
@ -173,7 +175,19 @@ func Main(clientBuildFS fs.FS) {
|
|||
}
|
||||
|
||||
// run the protection
|
||||
run(ctx, baseLogger, opts, clientBuildFS, glTokenFileRoot, done, sigHdlr, workDir, confPath, pidFilePath)
|
||||
run(
|
||||
ctx,
|
||||
baseLogger,
|
||||
opts,
|
||||
clientBuildFS,
|
||||
glTokenFileRoot,
|
||||
done,
|
||||
sigHdlr,
|
||||
workDir,
|
||||
confPath,
|
||||
pidFilePath,
|
||||
hc,
|
||||
)
|
||||
}
|
||||
|
||||
// setupContext initializes [globalContext] fields. It also reads and upgrades
|
||||
|
|
@ -185,24 +199,16 @@ func setupContext(
|
|||
workDir string,
|
||||
confPath string,
|
||||
isFirstRun bool,
|
||||
) (err error) {
|
||||
if !opts.noEtcHosts {
|
||||
err = setupHostsContainer(ctx, baseLogger)
|
||||
if err != nil {
|
||||
// Don't wrap the error, because it's informative enough as is.
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
) {
|
||||
if isFirstRun {
|
||||
baseLogger.InfoContext(ctx, "this is the first time adguard home has been launched")
|
||||
checkNetworkPermissions(ctx, baseLogger)
|
||||
|
||||
return nil
|
||||
return
|
||||
}
|
||||
|
||||
// TODO(s.chzhen): Consider adding a key prefix.
|
||||
err = parseConfig(ctx, baseLogger, workDir, confPath)
|
||||
err := parseConfig(ctx, baseLogger, workDir, confPath)
|
||||
if err != nil {
|
||||
baseLogger.ErrorContext(ctx, "failed to parse configuration file", slogutil.KeyError, err)
|
||||
|
||||
|
|
@ -214,8 +220,6 @@ func setupContext(
|
|||
|
||||
os.Exit(osutil.ExitCodeSuccess)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// logIfUnsupported logs a formatted warning if the error is one of the
|
||||
|
|
@ -272,13 +276,15 @@ func configureOS(ctx context.Context, l *slog.Logger, conf *configuration) (err
|
|||
return nil
|
||||
}
|
||||
|
||||
// setupHostsContainer initializes the structures to keep up-to-date the hosts
|
||||
// newHostsContainer initializes the structures to keep up-to-date the hosts
|
||||
// provided by the OS. baseLogger must not be nil.
|
||||
func setupHostsContainer(ctx context.Context, baseLogger *slog.Logger) (err error) {
|
||||
func newHostsContainer(
|
||||
ctx context.Context,
|
||||
baseLogger *slog.Logger,
|
||||
) (etcHosts *aghnet.HostsContainer, watcher aghos.FSWatcher, err error) {
|
||||
l := baseLogger.With(slogutil.KeyPrefix, "hosts")
|
||||
|
||||
var hostsWatcher aghos.FSWatcher
|
||||
hostsWatcher, err = aghos.NewOSWatcher(&aghos.OSWatcherConfig{
|
||||
watcher, err = aghos.NewOSWatcher(&aghos.OSWatcherConfig{
|
||||
Logger: baseLogger.With(slogutil.KeyPrefix, "hosts_watcher"),
|
||||
})
|
||||
if err != nil {
|
||||
|
|
@ -289,37 +295,39 @@ func setupHostsContainer(ctx context.Context, baseLogger *slog.Logger) (err erro
|
|||
err,
|
||||
)
|
||||
|
||||
hostsWatcher = aghos.EmptyFSWatcher{}
|
||||
watcher = aghos.EmptyFSWatcher{}
|
||||
}
|
||||
|
||||
paths, err := hostsfile.DefaultHostsPaths()
|
||||
if err != nil {
|
||||
return fmt.Errorf("getting default system hosts paths: %w", err)
|
||||
return nil, nil, fmt.Errorf("getting default system hosts paths: %w", err)
|
||||
}
|
||||
|
||||
globalContext.etcHosts, err = aghnet.NewHostsContainer(
|
||||
etcHosts, err = aghnet.NewHostsContainer(
|
||||
ctx,
|
||||
l,
|
||||
osutil.RootDirFS(),
|
||||
hostsWatcher,
|
||||
watcher,
|
||||
paths...,
|
||||
)
|
||||
if err != nil {
|
||||
closeErr := hostsWatcher.Shutdown(ctx)
|
||||
closeErr := watcher.Shutdown(ctx)
|
||||
if errors.Is(err, aghnet.ErrNoHostsPaths) {
|
||||
l.WarnContext(ctx, "initializing hosts container", slogutil.KeyError, err)
|
||||
|
||||
return closeErr
|
||||
return nil, nil, closeErr
|
||||
}
|
||||
|
||||
return errors.Join(fmt.Errorf("initializing hosts container: %w", err), closeErr)
|
||||
err = fmt.Errorf("initializing hosts container: %w", err)
|
||||
|
||||
return nil, nil, errors.WithDeferred(err, closeErr)
|
||||
}
|
||||
|
||||
return hostsWatcher.Start(ctx)
|
||||
return etcHosts, watcher, watcher.Start(ctx)
|
||||
}
|
||||
|
||||
// initContextClients initializes Context clients and related fields. All
|
||||
// arguments must not be nil.
|
||||
// arguments except hc must not be nil.
|
||||
func initContextClients(
|
||||
ctx context.Context,
|
||||
logger *slog.Logger,
|
||||
|
|
@ -327,6 +335,7 @@ func initContextClients(
|
|||
confModifier agh.ConfigModifier,
|
||||
httpReg aghhttp.Registrar,
|
||||
workDir string,
|
||||
hc *aghnet.HostsContainer,
|
||||
) (err error) {
|
||||
//lint:ignore SA1019 Migration is not over.
|
||||
config.DHCP.WorkDir = workDir
|
||||
|
|
@ -355,7 +364,7 @@ func initContextClients(
|
|||
logger,
|
||||
config.Clients.Persistent,
|
||||
globalContext.dhcpServer,
|
||||
globalContext.etcHosts,
|
||||
hc,
|
||||
arpDB,
|
||||
config.Filtering,
|
||||
sigHdlr,
|
||||
|
|
@ -415,7 +424,7 @@ func setupBindOpts(opts options) (err error) {
|
|||
}
|
||||
|
||||
// setupDNSFilteringConf sets up DNS filtering configuration settings. All
|
||||
// arguments must not be nil.
|
||||
// arguments except hc must not be nil.
|
||||
func setupDNSFilteringConf(
|
||||
ctx context.Context,
|
||||
baseLogger *slog.Logger,
|
||||
|
|
@ -424,6 +433,7 @@ func setupDNSFilteringConf(
|
|||
confModifier agh.ConfigModifier,
|
||||
httpReg aghhttp.Registrar,
|
||||
workDir string,
|
||||
hc *aghnet.HostsContainer,
|
||||
) (err error) {
|
||||
const (
|
||||
dnsTimeout = 3 * time.Second
|
||||
|
|
@ -439,10 +449,9 @@ func setupDNSFilteringConf(
|
|||
|
||||
conf.Logger = baseLogger.With(slogutil.KeyPrefix, "filtering")
|
||||
|
||||
conf.EtcHosts = globalContext.etcHosts
|
||||
// TODO(s.chzhen): Use empty interface.
|
||||
if globalContext.etcHosts == nil || !config.DNS.HostsFileEnabled {
|
||||
conf.EtcHosts = nil
|
||||
if hc != nil && config.DNS.HostsFileEnabled {
|
||||
conf.EtcHosts = hc
|
||||
}
|
||||
|
||||
conf.ConfModifier = confModifier
|
||||
|
|
@ -631,6 +640,9 @@ type webConfig struct {
|
|||
// must not be nil.
|
||||
mux *http.ServeMux
|
||||
|
||||
// hostsContainer is used for DNS initialization on updates.
|
||||
hostsContainer *aghnet.HostsContainer
|
||||
|
||||
// configModifier is used to update the global configuration.
|
||||
configModifier agh.ConfigModifier
|
||||
|
||||
|
|
@ -683,6 +695,7 @@ func newWeb(ctx context.Context, conf *webConfig) (web *webAPI, err error) {
|
|||
tlsManager: conf.tlsManager,
|
||||
auth: conf.auth,
|
||||
mux: conf.mux,
|
||||
hostsContainer: conf.hostsContainer,
|
||||
|
||||
clientFS: clientFS,
|
||||
|
||||
|
|
@ -765,6 +778,7 @@ func run(
|
|||
workDir string,
|
||||
confPath string,
|
||||
pidFilePath string,
|
||||
hc *aghnet.HostsContainer,
|
||||
) {
|
||||
aghtls.Init(ctx, baseLogger.With(slogutil.KeyPrefix, "aghtls"))
|
||||
|
||||
|
|
@ -774,10 +788,9 @@ func run(
|
|||
mux := http.NewServeMux()
|
||||
httpReg := aghhttp.NewDefaultRegistrar(mux, mw.wrap)
|
||||
|
||||
err := setupContext(ctx, baseLogger, opts, workDir, confPath, isFirstRun)
|
||||
fatalOnError(err)
|
||||
setupContext(ctx, baseLogger, opts, workDir, confPath, isFirstRun)
|
||||
|
||||
err = configureOS(ctx, baseLogger, config)
|
||||
err := configureOS(ctx, baseLogger, config)
|
||||
fatalOnError(err)
|
||||
|
||||
// Clients package uses filtering package's static data
|
||||
|
|
@ -792,7 +805,7 @@ func run(
|
|||
confPath,
|
||||
)
|
||||
|
||||
err = initContextClients(ctx, baseLogger, sigHdlr, confModifier, httpReg, workDir)
|
||||
err = initContextClients(ctx, baseLogger, sigHdlr, confModifier, httpReg, workDir, hc)
|
||||
fatalOnError(err)
|
||||
|
||||
tlsMgr, err := initTLS(ctx, baseLogger, sigHdlr, confModifier, httpReg)
|
||||
|
|
@ -806,6 +819,7 @@ func run(
|
|||
confModifier,
|
||||
httpReg,
|
||||
workDir,
|
||||
hc,
|
||||
)
|
||||
fatalOnError(err)
|
||||
|
||||
|
|
@ -831,6 +845,7 @@ func run(
|
|||
tlsManager: tlsMgr,
|
||||
auth: auth,
|
||||
mux: mux,
|
||||
hostsContainer: hc,
|
||||
configModifier: confModifier,
|
||||
httpReg: httpReg,
|
||||
workDir: workDir,
|
||||
|
|
@ -853,7 +868,7 @@ func run(
|
|||
fatalOnError(err)
|
||||
|
||||
if !isFirstRun {
|
||||
runDNSServer(ctx, baseLogger, tlsMgr, confModifier, statsDir, querylogDir, httpReg)
|
||||
runDNSServer(ctx, baseLogger, tlsMgr, confModifier, statsDir, querylogDir, httpReg, hc)
|
||||
}
|
||||
|
||||
if !opts.noPermCheck {
|
||||
|
|
@ -876,8 +891,9 @@ func runDNSServer(
|
|||
statsDir string,
|
||||
querylogDir string,
|
||||
httpReg *aghhttp.DefaultRegistrar,
|
||||
hc *aghnet.HostsContainer,
|
||||
) {
|
||||
err := initDNS(ctx, slogLogger, tlsMgr, confModifier, httpReg, statsDir, querylogDir)
|
||||
err := initDNS(ctx, slogLogger, tlsMgr, confModifier, httpReg, statsDir, querylogDir, hc)
|
||||
fatalOnError(err)
|
||||
|
||||
tlsMgr.start(ctx)
|
||||
|
|
@ -1215,7 +1231,7 @@ func initWorkingDir(opts options) (workDir string, err error) {
|
|||
}
|
||||
|
||||
// cleanup stops and resets all the modules. l must not be nil.
|
||||
func cleanup(ctx context.Context, l *slog.Logger) {
|
||||
func cleanup(ctx context.Context, l *slog.Logger, hc *aghnet.HostsContainer) {
|
||||
l.InfoContext(ctx, "stopping adguard home")
|
||||
|
||||
if globalContext.web != nil {
|
||||
|
|
@ -1235,8 +1251,8 @@ func cleanup(ctx context.Context, l *slog.Logger) {
|
|||
}
|
||||
}
|
||||
|
||||
if globalContext.etcHosts != nil {
|
||||
if err = globalContext.etcHosts.Close(); err != nil {
|
||||
if hc != nil {
|
||||
if err = hc.Close(); err != nil {
|
||||
l.ErrorContext(ctx, "closing hosts container", slogutil.KeyError, err)
|
||||
}
|
||||
}
|
||||
|
|
@ -1392,7 +1408,12 @@ func cmdlineUpdate(
|
|||
//
|
||||
// TODO(e.burkov): We could probably initialize the internal resolver
|
||||
// separately.
|
||||
err := initDNSServer(ctx, nil, nil, nil, nil, nil, nil, tlsMgr, l, agh.EmptyConfigModifier{})
|
||||
params := dnsforward.DNSCreateParams{
|
||||
Logger: l,
|
||||
TLSConfigProvider: tlsMgr,
|
||||
}
|
||||
|
||||
err := initDNSServer(ctx, l, params, nil, tlsMgr, agh.EmptyConfigModifier{})
|
||||
fatalOnError(err)
|
||||
|
||||
l.InfoContext(ctx, "performing update via cli")
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ import (
|
|||
"log/slog"
|
||||
"os"
|
||||
|
||||
"github.com/AdguardTeam/AdGuardHome/internal/aghnet"
|
||||
"github.com/AdguardTeam/AdGuardHome/internal/aghos"
|
||||
"github.com/AdguardTeam/AdGuardHome/internal/ossvc"
|
||||
"github.com/AdguardTeam/AdGuardHome/internal/version"
|
||||
|
|
@ -41,6 +42,7 @@ type program struct {
|
|||
baseLogger *slog.Logger
|
||||
logger *slog.Logger
|
||||
sigHdlr *signalHandler
|
||||
hostsContainer *aghnet.HostsContainer
|
||||
gliNetTokenRoot *os.Root
|
||||
workDir string
|
||||
confPath string
|
||||
|
|
@ -67,6 +69,7 @@ func (p *program) Start(_ service.Service) (err error) {
|
|||
p.workDir,
|
||||
p.confPath,
|
||||
p.pidFilePath,
|
||||
p.hostsContainer,
|
||||
)
|
||||
|
||||
return nil
|
||||
|
|
@ -162,6 +165,7 @@ func handleServiceControlAction(
|
|||
workDir string,
|
||||
confPath string,
|
||||
pidFilePath string,
|
||||
hc *aghnet.HostsContainer,
|
||||
) (err error) {
|
||||
actionName := opts.serviceControlAction
|
||||
l.InfoContext(ctx, version.Full())
|
||||
|
|
@ -194,6 +198,7 @@ func handleServiceControlAction(
|
|||
workDir: workDir,
|
||||
confPath: confPath,
|
||||
pidFilePath: pidFilePath,
|
||||
hostsContainer: hc,
|
||||
}
|
||||
|
||||
return p.handleRun(ctx, baseLogger, runOpts)
|
||||
|
|
|
|||
|
|
@ -7,10 +7,12 @@ import (
|
|||
"sync"
|
||||
"syscall"
|
||||
|
||||
"github.com/AdguardTeam/AdGuardHome/internal/aghnet"
|
||||
"github.com/AdguardTeam/AdGuardHome/internal/aghtls"
|
||||
"github.com/AdguardTeam/AdGuardHome/internal/client"
|
||||
"github.com/AdguardTeam/golibs/logutil/slogutil"
|
||||
"github.com/AdguardTeam/golibs/osutil"
|
||||
"github.com/AdguardTeam/golibs/service"
|
||||
)
|
||||
|
||||
// signalHandler processes incoming signals. It reloads configurations of
|
||||
|
|
@ -129,3 +131,44 @@ func (h *signalHandler) reloadConfig(ctx context.Context) {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
// signalHandlerCleanup performs application resources cleanup for
|
||||
// [signalHandler].
|
||||
type signalHandlerCleanup struct {
|
||||
logger *slog.Logger
|
||||
hostsContainer *aghnet.HostsContainer
|
||||
glTokenFileRoot *os.Root
|
||||
hcWatcher service.Interface
|
||||
done chan struct{}
|
||||
pidFilePath string
|
||||
glinetMode bool
|
||||
}
|
||||
|
||||
// cleanup performs application cleanup.
|
||||
func (c *signalHandlerCleanup) cleanup(ctx context.Context) {
|
||||
defer close(c.done)
|
||||
|
||||
cleanup(ctx, c.logger, c.hostsContainer)
|
||||
cleanupAlways(ctx, c.logger, c.pidFilePath)
|
||||
|
||||
if c.glinetMode {
|
||||
err := c.glTokenFileRoot.Close()
|
||||
checkCleanupErr(ctx, c.logger, err, "closing glinet token root")
|
||||
}
|
||||
|
||||
if c.hcWatcher != nil {
|
||||
err := c.hcWatcher.Shutdown(ctx)
|
||||
checkCleanupErr(ctx, c.logger, err, "shutting down hosts file watcher")
|
||||
}
|
||||
}
|
||||
|
||||
// checkCleanupErr logs err and exits with [osutil.ExitCodeFailure] if err is
|
||||
// not nil. l must not be nil.
|
||||
func checkCleanupErr(ctx context.Context, l *slog.Logger, err error, msg string) {
|
||||
if err == nil {
|
||||
return
|
||||
}
|
||||
|
||||
l.ErrorContext(ctx, msg, slogutil.KeyError, err)
|
||||
os.Exit(osutil.ExitCodeFailure)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -77,6 +77,9 @@ type webAPIConfig struct {
|
|||
// must not be nil.
|
||||
mux *http.ServeMux
|
||||
|
||||
// hostsContainer is used for DNS initialization on updates.
|
||||
hostsContainer *aghnet.HostsContainer
|
||||
|
||||
// clientFS is used to initialize file server. It must not be nil.
|
||||
clientFS fs.FS
|
||||
|
||||
|
|
@ -231,6 +234,9 @@ type webAPI struct {
|
|||
// auth stores web user information and handles authentication.
|
||||
auth *auth
|
||||
|
||||
// hostsContainer is used for DNS initialization on updates.
|
||||
hostsContainer *aghnet.HostsContainer
|
||||
|
||||
// httpsServer is the server that handles HTTPS traffic. If it is not nil,
|
||||
// [Web.http3Server] must also not be nil.
|
||||
//
|
||||
|
|
@ -252,16 +258,17 @@ func newWebAPI(ctx context.Context, conf *webAPIConfig) (w *webAPI) {
|
|||
conf.logger.InfoContext(ctx, "initializing")
|
||||
|
||||
w = &webAPI{
|
||||
conf: conf,
|
||||
confModifier: conf.confModifier,
|
||||
httpReg: conf.httpReg,
|
||||
cmdCons: conf.CommandConstructor,
|
||||
logger: conf.logger,
|
||||
baseLogger: conf.baseLogger,
|
||||
tlsManager: conf.tlsManager,
|
||||
auth: conf.auth,
|
||||
pidFilePath: conf.pidFilePath,
|
||||
startTime: time.Now(),
|
||||
conf: conf,
|
||||
confModifier: conf.confModifier,
|
||||
httpReg: conf.httpReg,
|
||||
cmdCons: conf.CommandConstructor,
|
||||
logger: conf.logger,
|
||||
baseLogger: conf.baseLogger,
|
||||
tlsManager: conf.tlsManager,
|
||||
auth: conf.auth,
|
||||
pidFilePath: conf.pidFilePath,
|
||||
startTime: time.Now(),
|
||||
hostsContainer: conf.hostsContainer,
|
||||
}
|
||||
|
||||
clientFS := http.FileServer(http.FS(conf.clientFS))
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue