diff --git a/libcontainer/nsinit/exec.go b/libcontainer/nsinit/exec.go index 73842f7..c07c45d 100644 --- a/libcontainer/nsinit/exec.go +++ b/libcontainer/nsinit/exec.go @@ -50,8 +50,13 @@ func (ns *linuxNs) Exec(container *libcontainer.Container, term Terminal, args [ if err := command.Start(); err != nil { return -1, err } + + started, err := system.GetProcessStartTime(command.Process.Pid) + if err != nil { + return -1, err + } ns.logger.Printf("writting pid %d to file\n", command.Process.Pid) - if err := ns.stateWriter.WritePid(command.Process.Pid); err != nil { + if err := ns.stateWriter.WritePid(command.Process.Pid, started); err != nil { command.Process.Kill() return -1, err } diff --git a/libcontainer/nsinit/state.go b/libcontainer/nsinit/state.go index af38008..26d7fa4 100644 --- a/libcontainer/nsinit/state.go +++ b/libcontainer/nsinit/state.go @@ -10,7 +10,7 @@ import ( // StateWriter handles writing and deleting the pid file // on disk type StateWriter interface { - WritePid(pid int) error + WritePid(pid int, startTime string) error DeletePid() error } @@ -19,10 +19,18 @@ type DefaultStateWriter struct { } // writePidFile writes the namespaced processes pid to pid in the rootfs for the container -func (d *DefaultStateWriter) WritePid(pid int) error { - return ioutil.WriteFile(filepath.Join(d.Root, "pid"), []byte(fmt.Sprint(pid)), 0655) +func (d *DefaultStateWriter) WritePid(pid int, startTime string) error { + err := ioutil.WriteFile(filepath.Join(d.Root, "pid"), []byte(fmt.Sprint(pid)), 0655) + if err != nil { + return err + } + return ioutil.WriteFile(filepath.Join(d.Root, "start"), []byte(startTime), 0655) } func (d *DefaultStateWriter) DeletePid() error { - return os.Remove(filepath.Join(d.Root, "pid")) + err := os.Remove(filepath.Join(d.Root, "pid")) + if serr := os.Remove(filepath.Join(d.Root, "start")); err == nil { + err = serr + } + return err } diff --git a/system/proc.go b/system/proc.go new file mode 100644 index 0000000..a492346 --- /dev/null +++ b/system/proc.go @@ -0,0 +1,26 @@ +package system + +import ( + "io/ioutil" + "path/filepath" + "strconv" + "strings" +) + +// look in /proc to find the process start time so that we can verify +// that this pid has started after ourself +func GetProcessStartTime(pid int) (string, error) { + data, err := ioutil.ReadFile(filepath.Join("/proc", strconv.Itoa(pid), "stat")) + if err != nil { + return "", err + } + parts := strings.Split(string(data), " ") + // the starttime is located at pos 22 + // from the man page + // + // starttime %llu (was %lu before Linux 2.6) + // (22) The time the process started after system boot. In kernels before Linux 2.6, this + // value was expressed in jiffies. Since Linux 2.6, the value is expressed in clock ticks + // (divide by sysconf(_SC_CLK_TCK)). + return parts[22-1], nil // starts at 1 +}