Browse code

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 <jostarks@microsoft.com>

John Starks authored on 2016/04/19 07:09:55
Showing 4 changed files
... ...
@@ -7,7 +7,6 @@ import (
7 7
 	"fmt"
8 8
 	"io/ioutil"
9 9
 	"os"
10
-	"path/filepath"
11 10
 	"strconv"
12 11
 	"strings"
13 12
 )
... ...
@@ -21,7 +20,7 @@ func checkPIDFileAlreadyExists(path string) error {
21 21
 	if pidByte, err := ioutil.ReadFile(path); err == nil {
22 22
 		pidString := strings.TrimSpace(string(pidByte))
23 23
 		if pid, err := strconv.Atoi(pidString); err == nil {
24
-			if _, err := os.Stat(filepath.Join("/proc", strconv.Itoa(pid))); err == nil {
24
+			if processExists(pid) {
25 25
 				return fmt.Errorf("pid file found, ensure docker is not running or delete %s", path)
26 26
 			}
27 27
 		}
... ...
@@ -13,11 +13,17 @@ func TestNewAndRemove(t *testing.T) {
13 13
 		t.Fatal("Could not create test directory")
14 14
 	}
15 15
 
16
-	file, err := New(filepath.Join(dir, "testfile"))
16
+	path := filepath.Join(dir, "testfile")
17
+	file, err := New(path)
17 18
 	if err != nil {
18 19
 		t.Fatal("Could not create test file", err)
19 20
 	}
20 21
 
22
+	_, err = New(path)
23
+	if err == nil {
24
+		t.Fatal("Test file creation not blocked")
25
+	}
26
+
21 27
 	if err := file.Remove(); err != nil {
22 28
 		t.Fatal("Could not delete created test file")
23 29
 	}
24 30
new file mode 100644
... ...
@@ -0,0 +1,16 @@
0
+// +build !windows
1
+
2
+package pidfile
3
+
4
+import (
5
+	"os"
6
+	"path/filepath"
7
+	"strconv"
8
+)
9
+
10
+func processExists(pid int) bool {
11
+	if _, err := os.Stat(filepath.Join("/proc", strconv.Itoa(pid))); err == nil {
12
+		return true
13
+	}
14
+	return false
15
+}
0 16
new file mode 100644
... ...
@@ -0,0 +1,23 @@
0
+package pidfile
1
+
2
+import "syscall"
3
+
4
+const (
5
+	processQueryLimitedInformation = 0x1000
6
+
7
+	stillActive = 259
8
+)
9
+
10
+func processExists(pid int) bool {
11
+	h, err := syscall.OpenProcess(processQueryLimitedInformation, false, uint32(pid))
12
+	if err != nil {
13
+		return false
14
+	}
15
+	var c uint32
16
+	err = syscall.GetExitCodeProcess(h, &c)
17
+	syscall.Close(h)
18
+	if err != nil {
19
+		return c == stillActive
20
+	}
21
+	return true
22
+}