Fix Windows agent self-update restart failure
syscall.Exec is not supported on Windows, causing self-update to fail with "failed to restart: not supported by windows". Split restart logic into platform-specific files: - restart_unix.go: Uses syscall.Exec for in-place process replacement - restart_windows.go: Uses os.Exit(0) to let Windows SCM restart service Related to #735
This commit is contained in:
parent
151db60267
commit
d89ba45284
3 changed files with 46 additions and 10 deletions
22
internal/agentupdate/restart_unix.go
Normal file
22
internal/agentupdate/restart_unix.go
Normal file
|
|
@ -0,0 +1,22 @@
|
||||||
|
//go:build !windows
|
||||||
|
|
||||||
|
package agentupdate
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
"syscall"
|
||||||
|
)
|
||||||
|
|
||||||
|
// restartProcess replaces the current process with a new instance.
|
||||||
|
// On Unix-like systems, this uses syscall.Exec for an in-place restart.
|
||||||
|
func restartProcess(execPath string) error {
|
||||||
|
args := os.Args
|
||||||
|
env := os.Environ()
|
||||||
|
|
||||||
|
if err := syscall.Exec(execPath, args, env); err != nil {
|
||||||
|
return fmt.Errorf("failed to restart: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
22
internal/agentupdate/restart_windows.go
Normal file
22
internal/agentupdate/restart_windows.go
Normal file
|
|
@ -0,0 +1,22 @@
|
||||||
|
//go:build windows
|
||||||
|
|
||||||
|
package agentupdate
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os"
|
||||||
|
)
|
||||||
|
|
||||||
|
// restartProcess triggers a restart on Windows.
|
||||||
|
// For Windows services, we exit cleanly and rely on the Service Control Manager
|
||||||
|
// to restart the service (services are typically configured with automatic recovery).
|
||||||
|
// For non-service processes, os.Exit(0) is still appropriate as the process will
|
||||||
|
// restart with the new binary on next invocation.
|
||||||
|
func restartProcess(execPath string) error {
|
||||||
|
// Exit with code 0 to signal clean shutdown.
|
||||||
|
// Windows Service Control Manager will restart the service if configured
|
||||||
|
// for automatic recovery (which is the default for our PowerShell installer).
|
||||||
|
os.Exit(0)
|
||||||
|
|
||||||
|
// This line is never reached, but satisfies the compiler
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
@ -18,7 +18,6 @@ import (
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"runtime"
|
"runtime"
|
||||||
"strings"
|
"strings"
|
||||||
"syscall"
|
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/rcourtman/pulse-go-rewrite/internal/utils"
|
"github.com/rcourtman/pulse-go-rewrite/internal/utils"
|
||||||
|
|
@ -430,15 +429,8 @@ func (u *Updater) performUpdate(ctx context.Context) error {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Restart with same arguments
|
// Restart the process using platform-specific implementation
|
||||||
args := os.Args
|
return restartProcess(execPath)
|
||||||
env := os.Environ()
|
|
||||||
|
|
||||||
if err := syscall.Exec(execPath, args, env); err != nil {
|
|
||||||
return fmt.Errorf("failed to restart: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// determineArch returns the architecture string for download URLs (e.g., "linux-amd64", "darwin-arm64").
|
// determineArch returns the architecture string for download URLs (e.g., "linux-amd64", "darwin-arm64").
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue