Pull request 2587: AGDNS-3681-improve-ossvc-code

Squashed commit of the following:

commit f15603569d921e048ced6539b5c2c05511a2f617
Author: Maksim Kazantsev <m.kazantsev@adguard.com>
Date:   Wed Feb 18 14:49:27 2026 +0300

    ossvc: replace !windows with unix;

commit 364291f76a24bc0f5cdb390596fd96072462f73b
Author: Maksim Kazantsev <m.kazantsev@adguard.com>
Date:   Wed Feb 18 14:42:11 2026 +0300

    ossvc: fix comment;

commit 068286ff10b8670c10d82ea812b763be4083bec4
Author: Maksim Kazantsev <m.kazantsev@adguard.com>
Date:   Wed Feb 18 14:29:02 2026 +0300

    ossvc: rm named return error value;

commit 43f966c41f6785cbe9334ca67061f4d5ba2e1a8e
Author: Maksim Kazantsev <m.kazantsev@adguard.com>
Date:   Wed Feb 18 14:26:57 2026 +0300

    ossvc: return one general Reload method; add several unexported implementation of the reload for each OS; upd docs;

commit 406434a91f9fb2683b3d0783cb5eec59d641948e
Author: Maksim Kazantsev <m.kazantsev@adguard.com>
Date:   Wed Feb 18 14:11:06 2026 +0300

    ossvcs: add docs for the windows impl of Reload; upd docs for the unix impl of Reload; rm receiver name;

commit 4c1b8c05060517d00347b03d1fc97a85edd86aaa
Author: Maksim Kazantsev <m.kazantsev@adguard.com>
Date:   Wed Feb 18 13:47:12 2026 +0300

    ossvc: decrease cognitive complexity in Reload method; mk different impls for Reload method on Windows and UNIX operating systems;

commit 088828a7ae64d930ca253a1c7deee8841b7f93f1
Author: Maksim Kazantsev <maksimkazantsev.job.it@gmail.com>
Date:   Wed Feb 18 11:42:55 2026 +0300

    make: add ossvc to lists of linted packages;

commit 4aea083cbd7753e452adf8dfa6c1016e64a95d59
Author: Maksim Kazantsev <maksimkazantsev.job.it@gmail.com>
Date:   Tue Feb 17 19:52:08 2026 +0300

    make: add ossvc package to the list of packages;
This commit is contained in:
Maksim Kazantsev 2026-02-18 12:07:17 +00:00
parent 2b92b779e7
commit 94a3a4fa62
4 changed files with 81 additions and 48 deletions

View file

@ -1,15 +1,12 @@
package ossvc
import (
"bytes"
"context"
"fmt"
"log/slog"
"os"
"path/filepath"
"runtime"
"strconv"
"syscall"
"github.com/AdguardTeam/AdGuardHome/internal/aghos"
"github.com/AdguardTeam/golibs/errors"
@ -123,51 +120,8 @@ func (m *manager) Status(ctx context.Context, name ServiceName) (status Status,
var _ ReloadManager = (*manager)(nil)
// Reload implements the [ReloadManager] interface for *manager.
//
// TODO(e.burkov): On Windows just don't implement this interface.
func (m *manager) Reload(ctx context.Context, name ServiceName) (err error) {
if runtime.GOOS == "windows" {
return errors.ErrUnsupported
}
nameStr := string(name)
var pid int
pidFile := filepath.Join("/var", "run", nameStr+".pid")
data, err := os.ReadFile(pidFile)
if err != nil {
if !errors.Is(err, os.ErrNotExist) {
return fmt.Errorf("reading service pid file: %w", err)
}
pid, err = aghos.PIDByCommand(ctx, m.logger, nameStr, os.Getpid())
if err != nil {
return fmt.Errorf("finding process: %w", err)
}
} else {
parts := bytes.SplitN(data, []byte("\n"), 2)
if len(parts) == 0 {
return fmt.Errorf("parsing %q: %w", pidFile, errors.ErrEmptyValue)
}
pidStr := string(bytes.TrimSpace(parts[0]))
pid, err = strconv.Atoi(pidStr)
if err != nil {
return fmt.Errorf("parsing pid from %q: %w", pidFile, err)
}
}
proc, err := os.FindProcess(pid)
if err != nil {
return fmt.Errorf("finding process with pid %d: %w", pid, err)
}
err = proc.Signal(syscall.SIGHUP)
if err != nil {
return fmt.Errorf("sending sighup to process with pid %d: %w", pid, err)
}
return nil
return m.reload(ctx, name)
}
// install installs the service in the service manager.
@ -364,7 +318,7 @@ func (m *manager) runInitdCommand(
}
// emptyInterface is an empty implementation of the [service.Interface], as the
// actual implementation is onlyy needed for the [service.Service.Run] method.
// actual implementation is only needed for the [service.Service.Run] method.
type emptyInterface struct{}
// type check

View file

@ -0,0 +1,61 @@
//go:build unix
package ossvc
import (
"bytes"
"context"
"fmt"
"os"
"path/filepath"
"strconv"
"syscall"
"github.com/AdguardTeam/AdGuardHome/internal/aghos"
"github.com/AdguardTeam/golibs/errors"
)
// reload is a UNIX platform implementation for the Reload method of
// [ReloadManager] interface for *manager.
func (m *manager) reload(ctx context.Context, name ServiceName) (err error) {
nameStr := string(name)
var pid int
pidFile := filepath.Join("/var", "run", nameStr+".pid")
// #nosec CWE-22 -- The name of the variable is always predictable, it is a
// constant.
data, err := os.ReadFile(pidFile)
if err != nil {
if !errors.Is(err, os.ErrNotExist) {
return fmt.Errorf("reading service pid file: %w", err)
}
pid, err = aghos.PIDByCommand(ctx, m.logger, nameStr, os.Getpid())
if err != nil {
return fmt.Errorf("finding process: %w", err)
}
} else {
parts := bytes.SplitN(data, []byte("\n"), 2)
if len(parts) == 0 {
return fmt.Errorf("parsing %q: %w", pidFile, errors.ErrEmptyValue)
}
pidStr := string(bytes.TrimSpace(parts[0]))
pid, err = strconv.Atoi(pidStr)
if err != nil {
return fmt.Errorf("parsing pid from %q: %w", pidFile, err)
}
}
proc, err := os.FindProcess(pid)
if err != nil {
return fmt.Errorf("finding process with pid %d: %w", pid, err)
}
err = proc.Signal(syscall.SIGHUP)
if err != nil {
return fmt.Errorf("sending sighup to process with pid %d: %w", pid, err)
}
return nil
}

View file

@ -0,0 +1,15 @@
//go:build windows
package ossvc
import (
"context"
"github.com/AdguardTeam/golibs/errors"
)
// reload is a Windows platform implementation of the Reload method of the
// [ReloadManager] interface for *manager.
func (*manager) reload(context.Context, ServiceName) error {
return errors.ErrUnsupported
}

View file

@ -210,6 +210,7 @@ run_linter "$go" tool gocognit --over='10' \
./internal/home/ \
./internal/ipset \
./internal/next/ \
./internal/ossvc/ \
./internal/rdns/ \
./internal/schedule/ \
./internal/stats/ \
@ -257,6 +258,7 @@ run_linter "$go" tool fieldalignment \
./internal/filtering/safesearch/ \
./internal/ipset/ \
./internal/next/... \
./internal/ossvc/ \
./internal/querylog/ \
./internal/rdns/ \
./internal/schedule/ \
@ -290,6 +292,7 @@ run_linter "$go" tool gosec --exclude=G115 --fmt=golint --quiet \
./internal/filtering/safesearch/ \
./internal/ipset/ \
./internal/next/ \
./internal/ossvc/ \
./internal/rdns/ \
./internal/schedule/ \
./internal/stats/ \