From b68bc651a8c2fda84f09e25a258557659ecb8c03 Mon Sep 17 00:00:00 2001 From: Michael Crosby Date: Fri, 11 Mar 2016 10:11:42 -0800 Subject: [PATCH] Handle start errors sync with runc Signed-off-by: Michael Crosby --- containerd-shim/main.go | 3 --- containerd-shim/process.go | 7 +++++-- runtime/container_linux.go | 42 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 47 insertions(+), 5 deletions(-) diff --git a/containerd-shim/main.go b/containerd-shim/main.go index 544fba2..a648317 100644 --- a/containerd-shim/main.go +++ b/containerd-shim/main.go @@ -12,15 +12,12 @@ import ( "github.com/docker/docker/pkg/term" ) -var runtimeLog string - func setupLogger() { f, err := os.OpenFile("/tmp/shim.log", os.O_CREATE|os.O_RDWR|os.O_APPEND, 0755) if err != nil { panic(err) } logrus.SetOutput(f) - runtimeLog = "/tmp/runtime.log" } // containerd-shim is a small shim that sits in front of a runtime implementation diff --git a/containerd-shim/process.go b/containerd-shim/process.go index b97b900..c87d2ed 100644 --- a/containerd-shim/process.go +++ b/containerd-shim/process.go @@ -84,7 +84,11 @@ func (p *process) start() error { if err != nil { return err } - args := []string{"--log", runtimeLog} + logPath := filepath.Join(cwd, "log.json") + args := []string{ + "--log", logPath, + "--log-format", "json", + } if p.state.Exec { args = append(args, "exec", "--process", filepath.Join(cwd, "process.json"), @@ -140,7 +144,6 @@ func (p *process) start() error { } p.containerPid = pid return nil - } func (p *process) pid() int { diff --git a/runtime/container_linux.go b/runtime/container_linux.go index 734f5a0..2c30a34 100644 --- a/runtime/container_linux.go +++ b/runtime/container_linux.go @@ -2,7 +2,9 @@ package runtime import ( "encoding/json" + "errors" "fmt" + "io" "io/ioutil" "os" "os/exec" @@ -308,6 +310,20 @@ func waitForStart(p *process, cmd *exec.Cmd) error { return err } if !alive { + // runc could have failed to run the container so lets get the error + // out of the logs + messages, err := readLogMessages(filepath.Join(p.root, "log.json")) + if err != nil { + if os.IsNotExist(err) { + return ErrContainerNotStarted + } + return err + } + for _, m := range messages { + if m.Level == "error" { + return errors.New(m.Msg) + } + } return ErrContainerNotStarted } time.Sleep(100 * time.Millisecond) @@ -362,3 +378,29 @@ func (o *oom) Close() error { } return err } + +type message struct { + Level string `json:"level"` + Msg string `json:"msg"` +} + +func readLogMessages(path string) ([]message, error) { + var out []message + f, err := os.Open(path) + if err != nil { + return nil, err + } + defer f.Close() + dec := json.NewDecoder(f) + for { + var m message + if err := dec.Decode(&m); err != nil { + if err == io.EOF { + return out, nil + } + return nil, err + } + out = append(out, m) + } + return out, nil +}