Pull request: home: fix exe path finding

Closes #4735.

Squashed commit of the following:

commit 8228e5f82c9d8056d5567a7f1b13b1365346c4d4
Author: Ainar Garipov <A.Garipov@AdGuard.COM>
Date:   Mon Jul 11 17:41:19 2022 +0300

    home: fix exe path finding
This commit is contained in:
Ainar Garipov 2022-07-11 18:18:17 +03:00
parent bf024fb985
commit 1eafb4e7cf
1 changed files with 38 additions and 29 deletions

View File

@ -117,7 +117,18 @@ func handleUpdate(w http.ResponseWriter, r *http.Request) {
return
}
err := Context.updater.Update()
// Retain the current absolute path of the executable, since the updater is
// likely to change the position current one to the backup directory.
//
// See https://github.com/AdguardTeam/AdGuardHome/issues/4735.
execPath, err := os.Executable()
if err != nil {
aghhttp.Error(r, w, http.StatusInternalServerError, "getting path: %s", err)
return
}
err = Context.updater.Update()
if err != nil {
aghhttp.Error(r, w, http.StatusInternalServerError, "%s", err)
@ -129,13 +140,10 @@ func handleUpdate(w http.ResponseWriter, r *http.Request) {
f.Flush()
}
// 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 due to the
// same reason.
go func() {
finishUpdate(context.Background())
}()
// 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(), execPath)
}
// versionResponse is the response for /control/version.json endpoint.
@ -174,45 +182,46 @@ func tlsConfUsesPrivilegedPorts(c *tlsConfigSettings) (ok bool) {
}
// finishUpdate completes an update procedure.
func finishUpdate(ctx context.Context) {
log.Info("Stopping all tasks")
func finishUpdate(ctx context.Context, execPath string) {
var err error
log.Info("stopping all tasks")
cleanup(ctx)
cleanupAlways()
curBinName, err := os.Executable()
if err != nil {
log.Fatalf("executable path request failed: %s", err)
}
if runtime.GOOS == "windows" {
if Context.runningAsService {
// Note:
// we can't restart the service via "kardianos/service" package - it kills the process first
// we can't start a new instance - Windows doesn't allow it
// 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.
//
// TODO(a.garipov): Recheck the claim above.
cmd := exec.Command("cmd", "/c", "net stop AdGuardHome & net start AdGuardHome")
err = cmd.Start()
if err != nil {
log.Fatalf("exec.Command() failed: %s", err)
log.Fatalf("restarting: stopping: %s", err)
}
os.Exit(0)
}
cmd := exec.Command(curBinName, os.Args[1:]...)
log.Info("Restarting: %v", cmd.Args)
cmd := exec.Command(execPath, os.Args[1:]...)
log.Info("restarting: %q %q", execPath, os.Args[1:])
cmd.Stdin = os.Stdin
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
err = cmd.Start()
if err != nil {
log.Fatalf("exec.Command() failed: %s", err)
log.Fatalf("restarting:: %s", err)
}
os.Exit(0)
} else {
log.Info("Restarting: %v", os.Args)
err = syscall.Exec(curBinName, os.Args, os.Environ())
if err != nil {
log.Fatalf("syscall.Exec() failed: %s", err)
}
// Unreachable code
}
log.Info("restarting: %q %q", execPath, os.Args[1:])
err = syscall.Exec(execPath, os.Args, os.Environ())
if err != nil {
log.Fatalf("restarting: %s", err)
}
}