Replace pid and started file with State type

Docker-DCO-1.1-Signed-off-by: Michael Crosby <michael@docker.com> (github: crosbymichael)
This commit is contained in:
Michael Crosby 2014-06-24 16:54:50 -07:00
parent e49f5f4788
commit 81e5a3f7a7
6 changed files with 64 additions and 53 deletions

View File

@ -56,12 +56,18 @@ func Exec(container *libcontainer.Config, term Terminal, rootfs, dataPath string
if err != nil {
return -1, err
}
if err := WritePid(dataPath, command.Process.Pid, started); err != nil {
state := &libcontainer.State{
Pid1: command.Process.Pid,
Pid1StartTime: started,
}
if err := libcontainer.WriteState(dataPath, state); err != nil {
command.Process.Kill()
command.Wait()
return -1, err
}
defer DeletePid(dataPath)
defer libcontainer.DeleteState(dataPath)
// Do this before syncing with child so that no children
// can escape the cgroup

View File

@ -13,7 +13,7 @@ import (
)
// ExecIn uses an existing pid and joins the pid's namespaces with the new command.
func ExecIn(container *libcontainer.Config, nspid int, args []string) error {
func ExecIn(container *libcontainer.Config, state *libcontainer.State, args []string) error {
// TODO(vmarmol): If this gets too long, send it over a pipe to the child.
// Marshall the container into JSON since it won't be available in the namespace.
containerJson, err := json.Marshal(container)
@ -22,7 +22,7 @@ func ExecIn(container *libcontainer.Config, nspid int, args []string) error {
}
// Enter the namespace and then finish setup
finalArgs := []string{os.Args[0], "nsenter", "--nspid", strconv.Itoa(nspid), "--containerjson", string(containerJson), "--"}
finalArgs := []string{os.Args[0], "nsenter", "--nspid", strconv.Itoa(state.Pid1), "--containerjson", string(containerJson), "--"}
finalArgs = append(finalArgs, args...)
if err := system.Execv(finalArgs[0], finalArgs[0:], os.Environ()); err != nil {
return err

View File

@ -1,28 +0,0 @@
package namespaces
import (
"fmt"
"io/ioutil"
"os"
"path/filepath"
)
// WritePid writes the namespaced processes pid to pid and it's start time
// to the path specified
func WritePid(path string, pid int, startTime string) error {
err := ioutil.WriteFile(filepath.Join(path, "pid"), []byte(fmt.Sprint(pid)), 0655)
if err != nil {
return err
}
return ioutil.WriteFile(filepath.Join(path, "start"), []byte(startTime), 0655)
}
// DeletePid removes the pid and started file from disk when the container's process
// dies and the container is cleanly removed
func DeletePid(path string) error {
err := os.Remove(filepath.Join(path, "pid"))
if serr := os.Remove(filepath.Join(path, "start")); err == nil {
err = serr
}
return err
}

View File

@ -19,19 +19,20 @@ var execCommand = cli.Command{
}
func execAction(context *cli.Context) {
var nspid, exitCode int
var exitCode int
container, err := loadContainer()
if err != nil {
log.Fatal(err)
}
if nspid, err = readPid(); err != nil && !os.IsNotExist(err) {
log.Fatalf("unable to read pid: %s", err)
state, err := libcontainer.LoadState(dataPath)
if err != nil && !os.IsNotExist(err) {
log.Fatalf("unable to read state.json: %s", err)
}
if nspid > 0 {
err = namespaces.ExecIn(container, nspid, []string(context.Args()))
if state != nil {
err = namespaces.ExecIn(container, state, []string(context.Args()))
} else {
term := namespaces.NewTerminal(os.Stdin, os.Stdout, os.Stderr, container.Tty)
exitCode, err = startContainer(container, term, dataPath, []string(context.Args()))

View File

@ -2,11 +2,9 @@ package main
import (
"encoding/json"
"io/ioutil"
"log"
"os"
"path/filepath"
"strconv"
"github.com/docker/libcontainer"
)
@ -26,20 +24,6 @@ func loadContainer() (*libcontainer.Config, error) {
return container, nil
}
func readPid() (int, error) {
data, err := ioutil.ReadFile(filepath.Join(dataPath, "pid"))
if err != nil {
return -1, err
}
pid, err := strconv.Atoi(string(data))
if err != nil {
return -1, err
}
return pid, nil
}
func openLog(name string) error {
f, err := os.OpenFile(name, os.O_CREATE|os.O_RDWR|os.O_APPEND, 0755)
if err != nil {

48
state.go Normal file
View File

@ -0,0 +1,48 @@
package libcontainer
import (
"encoding/json"
"os"
"path/filepath"
)
// State represents a running container's state
type State struct {
// Pid1 is the process id for the container's pid 1 in it's parent namespace
Pid1 int `json:"pid1,omitempty"`
// Pid1StartTime is the process start time for the container's pid 1
Pid1StartTime string `json:"pid1_start_time,omitempty"`
}
// WriteState writes the container's runtime state to a state.json file
// in the specified path
func WriteState(basePath string, state *State) error {
f, err := os.Create(filepath.Join(basePath, "state.json"))
if err != nil {
return err
}
defer f.Close()
return json.NewEncoder(f).Encode(state)
}
// LoadState reads the state.json file for a running container
func LoadState(basePath string) (*State, error) {
f, err := os.Open(filepath.Join(basePath, "state.json"))
if err != nil {
return nil, err
}
defer f.Close()
var state *State
if err := json.NewDecoder(f).Decode(&state); err != nil {
return nil, err
}
return state, nil
}
// DeleteState deletes the state.json file
func DeleteState(basePath string) error {
return os.Remove(filepath.Join(basePath, "state.json"))
}