From 95e8c2599cab42845a2ccc8afc5e1e1f966c2b74 Mon Sep 17 00:00:00 2001 From: John Starks Date: Mon, 18 Apr 2016 15:09:55 -0700 Subject: [PATCH] Windows: don't overwrite PID file if process exists pidfile.New() was opening a file in /proc to determine if the owning process still exists. Use syscall.OpenProcess() on Windows instead. Other OSes may also need to be updated here. Signed-off-by: John Starks --- pidfile/pidfile.go | 3 +-- pidfile/pidfile_test.go | 8 +++++++- pidfile/pidfile_unix.go | 16 ++++++++++++++++ pidfile/pidfile_windows.go | 23 +++++++++++++++++++++++ 4 files changed, 47 insertions(+), 3 deletions(-) create mode 100644 pidfile/pidfile_unix.go create mode 100644 pidfile/pidfile_windows.go diff --git a/pidfile/pidfile.go b/pidfile/pidfile.go index 58cc401..e1ac6be 100644 --- a/pidfile/pidfile.go +++ b/pidfile/pidfile.go @@ -7,7 +7,6 @@ import ( "fmt" "io/ioutil" "os" - "path/filepath" "strconv" "strings" ) @@ -21,7 +20,7 @@ func checkPIDFileAlreadyExists(path string) error { if pidByte, err := ioutil.ReadFile(path); err == nil { pidString := strings.TrimSpace(string(pidByte)) if pid, err := strconv.Atoi(pidString); err == nil { - if _, err := os.Stat(filepath.Join("/proc", strconv.Itoa(pid))); err == nil { + if processExists(pid) { return fmt.Errorf("pid file found, ensure docker is not running or delete %s", path) } } diff --git a/pidfile/pidfile_test.go b/pidfile/pidfile_test.go index d5ef870..73e8af7 100644 --- a/pidfile/pidfile_test.go +++ b/pidfile/pidfile_test.go @@ -13,11 +13,17 @@ func TestNewAndRemove(t *testing.T) { t.Fatal("Could not create test directory") } - file, err := New(filepath.Join(dir, "testfile")) + path := filepath.Join(dir, "testfile") + file, err := New(path) if err != nil { t.Fatal("Could not create test file", err) } + _, err = New(path) + if err == nil { + t.Fatal("Test file creation not blocked") + } + if err := file.Remove(); err != nil { t.Fatal("Could not delete created test file") } diff --git a/pidfile/pidfile_unix.go b/pidfile/pidfile_unix.go new file mode 100644 index 0000000..28f3dec --- /dev/null +++ b/pidfile/pidfile_unix.go @@ -0,0 +1,16 @@ +// +build !windows + +package 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 +} diff --git a/pidfile/pidfile_windows.go b/pidfile/pidfile_windows.go new file mode 100644 index 0000000..ae489c6 --- /dev/null +++ b/pidfile/pidfile_windows.go @@ -0,0 +1,23 @@ +package pidfile + +import "syscall" + +const ( + processQueryLimitedInformation = 0x1000 + + stillActive = 259 +) + +func processExists(pid int) bool { + h, err := syscall.OpenProcess(processQueryLimitedInformation, false, uint32(pid)) + if err != nil { + return false + } + var c uint32 + err = syscall.GetExitCodeProcess(h, &c) + syscall.Close(h) + if err != nil { + return c == stillActive + } + return true +}