ソースを参照

pkg/pidfile, pkg/process: use single implementation for process alive

Using the implementation from pkg/pidfile for windows, as that implementation
looks to be handling more cases to check if a process is still alive (or to be
considered alive).

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
Sebastiaan van Stijn 2 年 前
コミット
55d15e9d05

+ 2 - 1
pkg/pidfile/pidfile.go

@@ -10,6 +10,7 @@ import (
 	"path/filepath"
 	"strconv"
 
+	"github.com/docker/docker/pkg/process"
 	"github.com/docker/docker/pkg/system"
 )
 
@@ -22,7 +23,7 @@ func checkPIDFileAlreadyExists(path string) error {
 		return err
 	}
 	pid, err := strconv.Atoi(string(bytes.TrimSpace(pidByte)))
-	if err == nil && processExists(pid) {
+	if err == nil && process.Alive(pid) {
 		return fmt.Errorf("pid file found, ensure docker is not running or delete %s", path)
 	}
 	return nil

+ 0 - 15
pkg/pidfile/pidfile_darwin.go

@@ -1,15 +0,0 @@
-//go:build darwin
-// +build darwin
-
-package pidfile // import "github.com/docker/docker/pkg/pidfile"
-
-import (
-	"golang.org/x/sys/unix"
-)
-
-func processExists(pid int) bool {
-	// OS X does not have a proc filesystem.
-	// Use kill -0 pid to judge if the process exists.
-	err := unix.Kill(pid, 0)
-	return err == nil
-}

+ 0 - 17
pkg/pidfile/pidfile_unix.go

@@ -1,17 +0,0 @@
-//go:build !windows && !darwin
-// +build !windows,!darwin
-
-package pidfile // import "github.com/docker/docker/pkg/pidfile"
-
-import (
-	"os"
-	"path/filepath"
-	"strconv"
-)
-
-func processExists(pid int) bool {
-	if _, err := os.Stat(filepath.Join("/proc", strconv.Itoa(pid))); err == nil {
-		return true
-	}
-	return false
-}

+ 0 - 30
pkg/pidfile/pidfile_windows.go

@@ -1,30 +0,0 @@
-package pidfile // import "github.com/docker/docker/pkg/pidfile"
-
-import (
-	"golang.org/x/sys/windows"
-)
-
-func processExists(pid int) bool {
-	h, err := windows.OpenProcess(windows.PROCESS_QUERY_LIMITED_INFORMATION, false, uint32(pid))
-	if err != nil {
-		return false
-	}
-	var c uint32
-	err = windows.GetExitCodeProcess(h, &c)
-	_ = windows.CloseHandle(h)
-	if err != nil {
-		// From the GetExitCodeProcess function (processthreadsapi.h) API docs:
-		// https://learn.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-getexitcodeprocess
-		//
-		// The GetExitCodeProcess function returns a valid error code defined by the
-		// application only after the thread terminates. Therefore, an application should
-		// not use STILL_ACTIVE (259) as an error code (STILL_ACTIVE is a macro for
-		// STATUS_PENDING (minwinbase.h)). If a thread returns STILL_ACTIVE (259) as
-		// an error code, then applications that test for that value could interpret it
-		// to mean that the thread is still running, and continue to test for the
-		// completion of the thread after the thread has terminated, which could put
-		// the application into an infinite loop.
-		return c == uint32(windows.STATUS_PENDING)
-	}
-	return true
-}

+ 21 - 7
pkg/process/process_unix.go

@@ -1,5 +1,5 @@
-//go:build linux || freebsd || darwin
-// +build linux freebsd darwin
+//go:build !windows
+// +build !windows
 
 package process
 
@@ -7,18 +7,32 @@ import (
 	"bytes"
 	"fmt"
 	"os"
+	"path/filepath"
+	"runtime"
+	"strconv"
 
 	"golang.org/x/sys/unix"
 )
 
 // Alive returns true if process with a given pid is running.
 func Alive(pid int) bool {
-	err := unix.Kill(pid, 0)
-	if err == nil || err == unix.EPERM {
-		return true
-	}
+	switch runtime.GOOS {
+	case "darwin":
+		// OS X does not have a proc filesystem. Use kill -0 pid to judge if the
+		// process exists. From KILL(2): https://www.freebsd.org/cgi/man.cgi?query=kill&sektion=2&manpath=OpenDarwin+7.2.1
+		//
+		// Sig may be one of the signals specified in sigaction(2) or it may
+		// be 0, in which case error checking is performed but no signal is
+		// actually sent. This can be used to check the validity of pid.
+		err := unix.Kill(pid, 0)
 
-	return false
+		// Either the PID was found (no error) or we get an EPERM, which means
+		// the PID exists, but we don't have permissions to signal it.
+		return err == nil || err == unix.EPERM
+	default:
+		_, err := os.Stat(filepath.Join("/proc", strconv.Itoa(pid)))
+		return err == nil
+	}
 }
 
 // Kill force-stops a process.

+ 27 - 4
pkg/process/process_windows.go

@@ -1,12 +1,35 @@
 package process
 
-import "os"
+import (
+	"os"
+
+	"golang.org/x/sys/windows"
+)
 
 // Alive returns true if process with a given pid is running.
 func Alive(pid int) bool {
-	_, err := os.FindProcess(pid)
-
-	return err == nil
+	h, err := windows.OpenProcess(windows.PROCESS_QUERY_LIMITED_INFORMATION, false, uint32(pid))
+	if err != nil {
+		return false
+	}
+	var c uint32
+	err = windows.GetExitCodeProcess(h, &c)
+	_ = windows.CloseHandle(h)
+	if err != nil {
+		// From the GetExitCodeProcess function (processthreadsapi.h) API docs:
+		// https://learn.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-getexitcodeprocess
+		//
+		// The GetExitCodeProcess function returns a valid error code defined by the
+		// application only after the thread terminates. Therefore, an application should
+		// not use STILL_ACTIVE (259) as an error code (STILL_ACTIVE is a macro for
+		// STATUS_PENDING (minwinbase.h)). If a thread returns STILL_ACTIVE (259) as
+		// an error code, then applications that test for that value could interpret it
+		// to mean that the thread is still running, and continue to test for the
+		// completion of the thread after the thread has terminated, which could put
+		// the application into an infinite loop.
+		return c == uint32(windows.STATUS_PENDING)
+	}
+	return true
 }
 
 // Kill force-stops a process.