From f70a2648621ab1463299eabecda8e8c7584831c3 Mon Sep 17 00:00:00 2001
From: jingrui <jingrui@huawei.com>
Date: Thu, 3 Jan 2019 16:01:36 +0800
Subject: [PATCH 043/111] docker:  Make sure the pid exist in pidfile
 is docker

reason: cherry-pick commits to docker-18.09.

cherry-pick from
b4714e3321 | * Make sure the pid exist in pidfile is docker


Because of the recycling of used PIDs policy in kernel,
it could be possible that the process died with pidfile existing
and when the process boot next time, the pid in pidfile has been assigned
to another process, this would make the process can't be boot again without
removing the pidfile manually.

Change-Id: I237566682716733174900cd4dc76ce74ff9f4195
Signed-off-by: Lei Jitang <leijitang@huawei.com>
Signed-off-by: jingrui <jingrui@huawei.com>
---
 components/engine/pkg/pidfile/pidfile.go | 30 +++++++++++++++++++++++-
 1 file changed, 29 insertions(+), 1 deletion(-)

diff --git a/components/engine/pkg/pidfile/pidfile.go b/components/engine/pkg/pidfile/pidfile.go
index 0617a89e5f..485c00138b 100644
--- a/components/engine/pkg/pidfile/pidfile.go
+++ b/components/engine/pkg/pidfile/pidfile.go
@@ -4,6 +4,7 @@
 package pidfile // import "github.com/docker/docker/pkg/pidfile"
 
 import (
+	"bufio"
 	"fmt"
 	"io/ioutil"
 	"os"
@@ -19,12 +20,39 @@ type PIDFile struct {
 	path string
 }
 
+// isSameApplication check whether the pid exist in pidfile
+// is the the same application we are going to run.
+func isSameApplication(pid int) (bool, error) {
+	path := filepath.Join("/proc", strconv.Itoa(pid), "status")
+	file, err := os.Open(path)
+	if err != nil {
+		return false, err
+	}
+	defer file.Close()
+	sc := bufio.NewScanner(file)
+	for sc.Scan() {
+		lens := strings.Split(sc.Text(), ":")
+		if len(lens) == 2 && strings.TrimSpace(lens[0]) == "Name" {
+			if strings.TrimSpace(lens[1]) == os.Args[0] {
+				return true, nil
+			}
+			return false, nil
+		}
+	}
+	if err := sc.Err(); err != nil {
+		return false, err
+	}
+	return false, nil
+}
+
 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 processExists(pid) {
-				return fmt.Errorf("pid file found, ensure docker is not running or delete %s", path)
+				if same, err := isSameApplication(pid); same || (err != nil && !os.IsNotExist(err)) {
+					return fmt.Errorf("pid file found, ensure docker is not running or delete %s", path)
+				}
 			}
 		}
 	}
-- 
2.17.1

