Fixes #10958 by moving utils.daemon to pkg.pidfile.
Test cases were also added.
Updated the daemon to use the new pidfile.
Signed-off-by: Rick Wieman <git@rickw.nl>
| ... | ... |
@@ -36,6 +36,7 @@ import ( |
| 36 | 36 |
"github.com/docker/docker/pkg/namesgenerator" |
| 37 | 37 |
"github.com/docker/docker/pkg/parsers" |
| 38 | 38 |
"github.com/docker/docker/pkg/parsers/kernel" |
| 39 |
+ "github.com/docker/docker/pkg/pidfile" |
|
| 39 | 40 |
"github.com/docker/docker/pkg/resolvconf" |
| 40 | 41 |
"github.com/docker/docker/pkg/stringid" |
| 41 | 42 |
"github.com/docker/docker/pkg/sysinfo" |
| ... | ... |
@@ -836,12 +837,13 @@ func NewDaemonFromDirectory(config *Config, eng *engine.Engine) (*Daemon, error) |
| 836 | 836 |
// Claim the pidfile first, to avoid any and all unexpected race conditions. |
| 837 | 837 |
// Some of the init doesn't need a pidfile lock - but let's not try to be smart. |
| 838 | 838 |
if config.Pidfile != "" {
|
| 839 |
- if err := utils.CreatePidFile(config.Pidfile); err != nil {
|
|
| 839 |
+ file, err := pidfile.New(config.Pidfile) |
|
| 840 |
+ if err != nil {
|
|
| 840 | 841 |
return nil, err |
| 841 | 842 |
} |
| 842 | 843 |
eng.OnShutdown(func() {
|
| 843 | 844 |
// Always release the pidfile last, just in case |
| 844 |
- utils.RemovePidFile(config.Pidfile) |
|
| 845 |
+ file.Remove() |
|
| 845 | 846 |
}) |
| 846 | 847 |
} |
| 847 | 848 |
|
| 848 | 849 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,44 @@ |
| 0 |
+package pidfile |
|
| 1 |
+ |
|
| 2 |
+import ( |
|
| 3 |
+ "fmt" |
|
| 4 |
+ "io/ioutil" |
|
| 5 |
+ "log" |
|
| 6 |
+ "os" |
|
| 7 |
+ "path/filepath" |
|
| 8 |
+ "strconv" |
|
| 9 |
+) |
|
| 10 |
+ |
|
| 11 |
+type PidFile struct {
|
|
| 12 |
+ path string |
|
| 13 |
+} |
|
| 14 |
+ |
|
| 15 |
+func checkPidFileAlreadyExists(path string) error {
|
|
| 16 |
+ if pidString, err := ioutil.ReadFile(path); err == nil {
|
|
| 17 |
+ if pid, err := strconv.Atoi(string(pidString)); err == nil {
|
|
| 18 |
+ if _, err := os.Stat(filepath.Join("/proc", string(pid))); err == nil {
|
|
| 19 |
+ return fmt.Errorf("pid file found, ensure docker is not running or delete %s", path)
|
|
| 20 |
+ } |
|
| 21 |
+ } |
|
| 22 |
+ } |
|
| 23 |
+ return nil |
|
| 24 |
+} |
|
| 25 |
+ |
|
| 26 |
+func New(path string) (file *PidFile, err error) {
|
|
| 27 |
+ if err := checkPidFileAlreadyExists(path); err != nil {
|
|
| 28 |
+ return nil, err |
|
| 29 |
+ } |
|
| 30 |
+ |
|
| 31 |
+ file = &PidFile{path: path}
|
|
| 32 |
+ err = ioutil.WriteFile(path, []byte(fmt.Sprintf("%d", os.Getpid())), 0644)
|
|
| 33 |
+ |
|
| 34 |
+ return file, err |
|
| 35 |
+} |
|
| 36 |
+ |
|
| 37 |
+func (file PidFile) Remove() error {
|
|
| 38 |
+ if err := os.Remove(file.path); err != nil {
|
|
| 39 |
+ log.Printf("Error removing %s: %s", file.path, err)
|
|
| 40 |
+ return err |
|
| 41 |
+ } |
|
| 42 |
+ return nil |
|
| 43 |
+} |
| 0 | 44 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,32 @@ |
| 0 |
+package pidfile |
|
| 1 |
+ |
|
| 2 |
+import ( |
|
| 3 |
+ "io/ioutil" |
|
| 4 |
+ "os" |
|
| 5 |
+ "path/filepath" |
|
| 6 |
+ "testing" |
|
| 7 |
+) |
|
| 8 |
+ |
|
| 9 |
+func TestNewAndRemove(t *testing.T) {
|
|
| 10 |
+ dir, err := ioutil.TempDir(os.TempDir(), "test-pidfile") |
|
| 11 |
+ if err != nil {
|
|
| 12 |
+ t.Fatal("Could not create test directory")
|
|
| 13 |
+ } |
|
| 14 |
+ |
|
| 15 |
+ file, err := New(filepath.Join(dir, "testfile")) |
|
| 16 |
+ if err != nil {
|
|
| 17 |
+ t.Fatal("Could not create test file", err)
|
|
| 18 |
+ } |
|
| 19 |
+ |
|
| 20 |
+ if err := file.Remove(); err != nil {
|
|
| 21 |
+ t.Fatal("Could not delete created test file")
|
|
| 22 |
+ } |
|
| 23 |
+} |
|
| 24 |
+ |
|
| 25 |
+func TestRemoveInvalidPath(t *testing.T) {
|
|
| 26 |
+ file := PidFile{path: filepath.Join("foo", "bar")}
|
|
| 27 |
+ |
|
| 28 |
+ if err := file.Remove(); err == nil {
|
|
| 29 |
+ t.Fatal("Non-existing file doesn't give an error on delete")
|
|
| 30 |
+ } |
|
| 31 |
+} |
| 0 | 32 |
deleted file mode 100644 |
| ... | ... |
@@ -1,36 +0,0 @@ |
| 1 |
-package utils |
|
| 2 |
- |
|
| 3 |
-import ( |
|
| 4 |
- "fmt" |
|
| 5 |
- "io/ioutil" |
|
| 6 |
- "log" |
|
| 7 |
- "os" |
|
| 8 |
- "strconv" |
|
| 9 |
-) |
|
| 10 |
- |
|
| 11 |
-func CreatePidFile(pidfile string) error {
|
|
| 12 |
- if pidString, err := ioutil.ReadFile(pidfile); err == nil {
|
|
| 13 |
- pid, err := strconv.Atoi(string(pidString)) |
|
| 14 |
- if err == nil {
|
|
| 15 |
- if _, err := os.Stat(fmt.Sprintf("/proc/%d/", pid)); err == nil {
|
|
| 16 |
- return fmt.Errorf("pid file found, ensure docker is not running or delete %s", pidfile)
|
|
| 17 |
- } |
|
| 18 |
- } |
|
| 19 |
- } |
|
| 20 |
- |
|
| 21 |
- file, err := os.Create(pidfile) |
|
| 22 |
- if err != nil {
|
|
| 23 |
- return err |
|
| 24 |
- } |
|
| 25 |
- |
|
| 26 |
- defer file.Close() |
|
| 27 |
- |
|
| 28 |
- _, err = fmt.Fprintf(file, "%d", os.Getpid()) |
|
| 29 |
- return err |
|
| 30 |
-} |
|
| 31 |
- |
|
| 32 |
-func RemovePidFile(pidfile string) {
|
|
| 33 |
- if err := os.Remove(pidfile); err != nil {
|
|
| 34 |
- log.Printf("Error removing %s: %s", pidfile, err)
|
|
| 35 |
- } |
|
| 36 |
-} |