summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSimon Frei <freisim93@gmail.com>2022-08-14 21:25:45 +0200
committerGitHub <noreply@github.com>2022-08-14 21:25:45 +0200
commit5fd6278609be75141388a823198dd4e1a0dd3b74 (patch)
tree5df4bc4355fd70d192daab7a7b4e7dc6e6a72ad1
parenteb81f7400c418712045dcc5b73b33a2129f09c99 (diff)
cmd/syncthing: Work around binary in current dir restriction (fixes #8499) (#8500)
-rw-r--r--cmd/syncthing/monitor.go45
1 files changed, 35 insertions, 10 deletions
diff --git a/cmd/syncthing/monitor.go b/cmd/syncthing/monitor.go
index d15a449efc..fd76966a68 100644
--- a/cmd/syncthing/monitor.go
+++ b/cmd/syncthing/monitor.go
@@ -83,6 +83,15 @@ func monitorMain(options serveOptions) {
}
args := os.Args
+ binary := args[0]
+ if build.IsWindows {
+ var err error
+ binary, err = expandExecutableInCurrentDirectory(binary)
+ if err != nil {
+ l.Warnln("Error starting the main Syncthing process:", err)
+ panic("Error starting the main Syncthing process")
+ }
+ }
var restarts [restartCounts]time.Time
stopSign := make(chan os.Signal, 1)
@@ -104,7 +113,7 @@ func monitorMain(options serveOptions) {
copy(restarts[0:], restarts[1:])
restarts[len(restarts)-1] = time.Now()
- cmd := exec.Command(args[0], args[1:]...)
+ cmd := exec.Command(binary, args[1:]...)
cmd.Env = childEnv
stderr, err := cmd.StderrPipe()
@@ -180,7 +189,7 @@ func monitorMain(options serveOptions) {
// Restart the monitor process to release the .old
// binary as part of the upgrade process.
l.Infoln("Restarting monitor...")
- if err = restartMonitor(args); err != nil {
+ if err = restartMonitor(binary, args); err != nil {
l.Warnln("Restart:", err)
}
os.Exit(exitCode)
@@ -203,6 +212,21 @@ func monitorMain(options serveOptions) {
}
}
+func expandExecutableInCurrentDirectory(args0 string) (string, error) {
+ // Works around a restriction added in go1.19 that executables in the
+ // current directory are not resolved when specifying just an executable
+ // name (like e.g. "syncthing")
+ if !strings.ContainsRune(args0, os.PathSeparator) {
+ // Check if it's in PATH
+ _, err := exec.LookPath(args0)
+ if err != nil {
+ // Try to get the path to the current executable
+ return os.Executable()
+ }
+ }
+ return args0, nil
+}
+
func copyStderr(stderr io.Reader, dst io.Writer) {
br := bufio.NewReader(stderr)
@@ -309,7 +333,7 @@ func copyStdout(stdout io.Reader, dst io.Writer) {
}
}
-func restartMonitor(args []string) error {
+func restartMonitor(binary string, args []string) error {
// Set the STRESTART environment variable to indicate to the next
// process that this is a restart and not initial start. This prevents
// opening the browser on startup.
@@ -319,19 +343,20 @@ func restartMonitor(args []string) error {
// syscall.Exec is the cleanest way to restart on Unixes as it
// replaces the current process with the new one, keeping the pid and
// controlling terminal and so on
- return restartMonitorUnix(args)
+ return restartMonitorUnix(binary, args)
}
// but it isn't supported on Windows, so there we start a normal
// exec.Command and return.
- return restartMonitorWindows(args)
+ return restartMonitorWindows(binary, args)
}
-func restartMonitorUnix(args []string) error {
- if !strings.ContainsRune(args[0], os.PathSeparator) {
+func restartMonitorUnix(binary string, args []string) error {
+ if !strings.ContainsRune(binary, os.PathSeparator) {
// The path to the binary doesn't contain a slash, so it should be
// found in $PATH.
- binary, err := exec.LookPath(args[0])
+ var err error
+ binary, err = exec.LookPath(binary)
if err != nil {
return err
}
@@ -341,8 +366,8 @@ func restartMonitorUnix(args []string) error {
return syscall.Exec(args[0], args, os.Environ())
}
-func restartMonitorWindows(args []string) error {
- cmd := exec.Command(args[0], args[1:]...)
+func restartMonitorWindows(binary string, args []string) error {
+ cmd := exec.Command(binary, args[1:]...)
// Retain the standard streams
cmd.Stderr = os.Stderr
cmd.Stdout = os.Stdout