From 9e680cbc6381634d09b1ff220f5b81243b6e3e25 Mon Sep 17 00:00:00 2001 From: Brent Baude Date: Tue, 22 Aug 2023 15:56:00 -0500 Subject: [PATCH] Fixups for stopping gvproxy Paul found logic errors in my earlier code for finding processes and sending signals. Some of the logic errors are associated with how methods behave on different operating systems. Created a darwin and linux approach and a windows approach. Signed-off-by: Brent Baude [NO NEW TESTS NEEDED] --- pkg/machine/gvproxy.go | 20 ++++++++++++-------- pkg/machine/gvproxy_unix.go | 24 ++++++++++++++++++++++++ pkg/machine/gvproxy_windows.go | 10 ++++++++++ 3 files changed, 46 insertions(+), 8 deletions(-) create mode 100644 pkg/machine/gvproxy_unix.go create mode 100644 pkg/machine/gvproxy_windows.go diff --git a/pkg/machine/gvproxy.go b/pkg/machine/gvproxy.go index 8cc8f00443..f159b8266c 100644 --- a/pkg/machine/gvproxy.go +++ b/pkg/machine/gvproxy.go @@ -2,7 +2,6 @@ package machine import ( "fmt" - "os" "strconv" "syscall" "time" @@ -19,7 +18,7 @@ const ( func backoffForProcess(pid int) error { sleepInterval := sleepTime for i := 0; i < loops; i++ { - proxyProc, err := os.FindProcess(pid) + proxyProc, err := findProcess(pid) if proxyProc == nil && err != nil { // process is killed, gone return nil //nolint: nilerr @@ -35,13 +34,16 @@ func backoffForProcess(pid int) error { // process to not exist. if the sigterm does not end the process after an interval, // then sigkill is sent. it also waits for the process to exit after the sigkill too. func waitOnProcess(processID int) error { - proxyProc, err := os.FindProcess(processID) + proxyProc, err := findProcess(processID) if err != nil { return err } // Try to kill the pid with sigterm if err := proxyProc.Signal(syscall.SIGTERM); err != nil { + if err == syscall.ESRCH { + return nil + } return err } @@ -50,14 +52,16 @@ func waitOnProcess(processID int) error { } // sigterm has not killed it yet, lets send a sigkill - proxyProc, err = os.FindProcess(processID) + proxyProc, err = findProcess(processID) if proxyProc == nil && err != nil { // process is killed, gone return nil //nolint: nilerr } if err := proxyProc.Signal(syscall.SIGKILL); err != nil { - // lets assume it is dead in this case - return nil //nolint: nilerr + if err == syscall.ESRCH { + return nil + } + return err } return backoffForProcess(processID) } @@ -72,8 +76,8 @@ func CleanupGVProxy(f VMFile) error { if err != nil { return fmt.Errorf("unable to convert pid to integer: %v", err) } - if err := waitOnProcess(proxyPid); err == nil { - return nil + if err := waitOnProcess(proxyPid); err != nil { + return err } return f.Delete() } diff --git a/pkg/machine/gvproxy_unix.go b/pkg/machine/gvproxy_unix.go new file mode 100644 index 0000000000..7168e09536 --- /dev/null +++ b/pkg/machine/gvproxy_unix.go @@ -0,0 +1,24 @@ +//go:build darwin || dragonfly || freebsd || linux || netbsd || openbsd +// +build darwin dragonfly freebsd linux netbsd openbsd + +package machine + +import ( + "os" + "syscall" +) + +func findProcess(pid int) (*os.Process, error) { + p, err := os.FindProcess(pid) + if err != nil { + return nil, err + } + // On unix, findprocess will always return a process even + // if the process is not found. you must send a 0 signal + // to the process to see if it is alive. + // https://pkg.go.dev/os#FindProcess + if err := p.Signal(syscall.Signal(0)); err != nil { + return nil, err + } + return p, nil +} diff --git a/pkg/machine/gvproxy_windows.go b/pkg/machine/gvproxy_windows.go new file mode 100644 index 0000000000..ee1f4b8be3 --- /dev/null +++ b/pkg/machine/gvproxy_windows.go @@ -0,0 +1,10 @@ +//go:build windows +// +build windows + +package machine + +import "os" + +func findProcess(pid int) (*os.Process, error) { + return os.FindProcess(pid) +}