From 59a4a009a07baab6d7f53018d92705b4871f8a59 Mon Sep 17 00:00:00 2001
From: Stanislav Chzhen <s.chzhen@adguard.com>
Date: Mon, 28 Aug 2023 16:40:46 +0300
Subject: [PATCH] Pull request 1977: 6100-fix-query-log

Updates #6100.

Squashed commit of the following:

commit f8a37b46620c8fbe7ff1cf06b70af3805c9dc049
Author: Stanislav Chzhen <s.chzhen@adguard.com>
Date:   Mon Aug 28 14:08:41 2023 +0300

    home: imp code

commit 2dd357fa3b41c36cec10ba136d4aecb0e41dbba3
Author: Stanislav Chzhen <s.chzhen@adguard.com>
Date:   Fri Aug 25 19:35:42 2023 +0300

    all: imp docs

commit 369f17897ab6befa78af163bead5deb8ceac0fa1
Author: Stanislav Chzhen <s.chzhen@adguard.com>
Date:   Fri Aug 25 19:26:14 2023 +0300

    all: upd chlog

commit c07d80ee437a9eeef547d308d00bcd12d52ed8ff
Author: Stanislav Chzhen <s.chzhen@adguard.com>
Date:   Fri Aug 25 16:22:58 2023 +0300

    home: fix more

commit 3872806618d09b7eaa19eb1ce5cd8df2d55c10ff
Author: Stanislav Chzhen <s.chzhen@adguard.com>
Date:   Thu Aug 24 15:35:22 2023 +0300

    home: fix query log
---
 CHANGELOG.md             |  2 ++
 internal/home/dns.go     |  4 ----
 internal/home/home.go    | 15 +++++++++------
 internal/home/service.go | 17 +++++++----------
 4 files changed, 18 insertions(+), 20 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 8d20d3e1..4959f325 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -69,6 +69,7 @@ In this release, the schema version has changed from 24 to 25.
 
 ### Fixed
 
+- Missing query log entries and statistics on service restart ([#6100]).
 - Occasional DNS-over-QUIC and DNS-over-HTTP/3 errors ([#6133]).
 - Legacy DNS rewrites containing IPv4-mapped IPv6 addresses are now matching the
   `AAAA` requests, not `A` ([#6050]).
@@ -84,6 +85,7 @@ In this release, the schema version has changed from 24 to 25.
 [#6050]: https://github.com/AdguardTeam/AdGuardHome/issues/6050
 [#6053]: https://github.com/AdguardTeam/AdGuardHome/issues/6053
 [#6093]: https://github.com/AdguardTeam/AdGuardHome/issues/6093
+[#6100]: https://github.com/AdguardTeam/AdGuardHome/issues/6100
 [#6122]: https://github.com/AdguardTeam/AdGuardHome/issues/6122
 [#6133]: https://github.com/AdguardTeam/AdGuardHome/issues/6133
 
diff --git a/internal/home/dns.go b/internal/home/dns.go
index df307cc1..bc485e36 100644
--- a/internal/home/dns.go
+++ b/internal/home/dns.go
@@ -502,14 +502,10 @@ func closeDNSServer() {
 		if err != nil {
 			log.Debug("closing stats: %s", err)
 		}
-
-		// TODO(e.burkov):  Find out if it's safe.
-		Context.stats = nil
 	}
 
 	if Context.queryLog != nil {
 		Context.queryLog.Close()
-		Context.queryLog = nil
 	}
 
 	log.Debug("all dns modules are closed")
diff --git a/internal/home/home.go b/internal/home/home.go
index b615a73b..f6c1024e 100644
--- a/internal/home/home.go
+++ b/internal/home/home.go
@@ -99,8 +99,11 @@ func Main(clientBuildFS fs.FS) {
 	// package flag.
 	opts := loadCmdLineOpts()
 
+	done := make(chan struct{})
+
 	signals := make(chan os.Signal, 1)
 	signal.Notify(signals, syscall.SIGINT, syscall.SIGTERM, syscall.SIGHUP, syscall.SIGQUIT)
+
 	go func() {
 		for {
 			sig := <-signals
@@ -112,19 +115,19 @@ func Main(clientBuildFS fs.FS) {
 			default:
 				cleanup(context.Background())
 				cleanupAlways()
-				os.Exit(0)
+				close(done)
 			}
 		}
 	}()
 
 	if opts.serviceControlAction != "" {
-		handleServiceControlAction(opts, clientBuildFS, signals)
+		handleServiceControlAction(opts, clientBuildFS, done)
 
 		return
 	}
 
 	// run the protection
-	run(opts, clientBuildFS)
+	run(opts, clientBuildFS, done)
 }
 
 // setupContext initializes [Context] fields.  It also reads and upgrades
@@ -504,7 +507,7 @@ func fatalOnError(err error) {
 }
 
 // run configures and starts AdGuard Home.
-func run(opts options, clientBuildFS fs.FS) {
+func run(opts options, clientBuildFS fs.FS, done chan struct{}) {
 	// Configure config filename.
 	initConfigFilename(opts)
 
@@ -609,8 +612,8 @@ func run(opts options, clientBuildFS fs.FS) {
 
 	Context.web.start()
 
-	// Wait indefinitely for other goroutines to complete their job.
-	select {}
+	// Wait for other goroutines to complete their job.
+	<-done
 }
 
 // initUsers initializes context auth module.  Clears config users field.
diff --git a/internal/home/service.go b/internal/home/service.go
index e98aa030..74128ec8 100644
--- a/internal/home/service.go
+++ b/internal/home/service.go
@@ -33,7 +33,7 @@ const (
 // daemon.
 type program struct {
 	clientBuildFS fs.FS
-	signals       chan os.Signal
+	done          chan struct{}
 	opts          options
 }
 
@@ -46,19 +46,16 @@ func (p *program) Start(_ service.Service) (err error) {
 	args := p.opts
 	args.runningAsService = true
 
-	go run(args, p.clientBuildFS)
+	go run(args, p.clientBuildFS, p.done)
 
 	return nil
 }
 
 // Stop implements service.Interface interface for *program.
 func (p *program) Stop(_ service.Service) (err error) {
-	select {
-	case p.signals <- syscall.SIGINT:
-		// Go on.
-	default:
-		// Stop should not block.
-	}
+	log.Info("service: stopping: waiting for cleanup")
+
+	<-p.done
 
 	return nil
 }
@@ -198,7 +195,7 @@ func restartService() (err error) {
 //   - run:  This is a special command that is not supposed to be used directly
 //     it is specified when we register a service, and it indicates to the app
 //     that it is being run as a service/daemon.
-func handleServiceControlAction(opts options, clientBuildFS fs.FS, signals chan os.Signal) {
+func handleServiceControlAction(opts options, clientBuildFS fs.FS, done chan struct{}) {
 	// Call chooseSystem explicitly to introduce OpenBSD support for service
 	// package.  It's a noop for other GOOS values.
 	chooseSystem()
@@ -232,7 +229,7 @@ func handleServiceControlAction(opts options, clientBuildFS fs.FS, signals chan
 
 	s, err := service.New(&program{
 		clientBuildFS: clientBuildFS,
-		signals:       signals,
+		done:          done,
 		opts:          runOpts,
 	}, svcConfig)
 	if err != nil {