diff --git a/libcontainer/container_linux.go b/libcontainer/container_linux.go index 19b8f3a7..4015c957 100644 --- a/libcontainer/container_linux.go +++ b/libcontainer/container_linux.go @@ -21,6 +21,7 @@ import ( "github.com/opencontainers/runc/libcontainer/cgroups" "github.com/opencontainers/runc/libcontainer/configs" "github.com/opencontainers/runc/libcontainer/criurpc" + "github.com/opencontainers/runc/libcontainer/utils" "github.com/vishvananda/netlink/nl" ) @@ -964,7 +965,7 @@ func (c *linuxContainer) saveState(s *State) error { return err } defer f.Close() - return json.NewEncoder(f).Encode(s) + return utils.WriteJSON(f, s) } func (c *linuxContainer) deleteState() error { diff --git a/libcontainer/factory_linux.go b/libcontainer/factory_linux.go index eb2bb5fb..d2f6b9ee 100644 --- a/libcontainer/factory_linux.go +++ b/libcontainer/factory_linux.go @@ -18,6 +18,7 @@ import ( "github.com/opencontainers/runc/libcontainer/cgroups/systemd" "github.com/opencontainers/runc/libcontainer/configs" "github.com/opencontainers/runc/libcontainer/configs/validate" + "github.com/opencontainers/runc/libcontainer/utils" ) const ( @@ -235,15 +236,15 @@ func (l *LinuxFactory) StartInitialization() (err error) { if err != nil { if _, ok := i.(*linuxStandardInit); ok { // Synchronisation only necessary for standard init. - if err := json.NewEncoder(pipe).Encode(procError); err != nil { + if err := utils.WriteJSON(pipe, syncT{procError}); err != nil { panic(err) } } - if err := json.NewEncoder(pipe).Encode(newSystemError(err)); err != nil { + if err := utils.WriteJSON(pipe, newSystemError(err)); err != nil { panic(err) } } else { - if err := json.NewEncoder(pipe).Encode(procStart); err != nil { + if err := utils.WriteJSON(pipe, syncT{procStart}); err != nil { panic(err) } } diff --git a/libcontainer/factory_linux_test.go b/libcontainer/factory_linux_test.go index dccc8db4..b0c0f496 100644 --- a/libcontainer/factory_linux_test.go +++ b/libcontainer/factory_linux_test.go @@ -3,7 +3,6 @@ package libcontainer import ( - "encoding/json" "io/ioutil" "os" "path/filepath" @@ -12,6 +11,7 @@ import ( "github.com/docker/docker/pkg/mount" "github.com/opencontainers/runc/libcontainer/configs" + "github.com/opencontainers/runc/libcontainer/utils" ) func newTestRoot() (string, error) { @@ -179,5 +179,5 @@ func marshal(path string, v interface{}) error { return err } defer f.Close() - return json.NewEncoder(f).Encode(v) + return utils.WriteJSON(f, v) } diff --git a/libcontainer/generic_error.go b/libcontainer/generic_error.go index e4872e2d..924d637b 100644 --- a/libcontainer/generic_error.go +++ b/libcontainer/generic_error.go @@ -18,6 +18,10 @@ const ( procRun ) +type syncT struct { + Type syncType `json:"type"` +} + var errorTemplate = template.Must(template.New("error").Parse(`Timestamp: {{.Timestamp}} Code: {{.ECode}} {{if .Message }} diff --git a/libcontainer/init_linux.go b/libcontainer/init_linux.go index 57e53782..918f1030 100644 --- a/libcontainer/init_linux.go +++ b/libcontainer/init_linux.go @@ -147,17 +147,16 @@ func finalizeNamespace(config *initConfig) error { // indicate that it is cleared to Exec. func syncParentReady(pipe io.ReadWriter) error { // Tell parent. - if err := json.NewEncoder(pipe).Encode(procReady); err != nil { + if err := utils.WriteJSON(pipe, syncT{procReady}); err != nil { return err } - // Wait for parent to give the all-clear. - var procSync syncType + var procSync syncT if err := json.NewDecoder(pipe).Decode(&procSync); err != nil { if err == io.EOF { return fmt.Errorf("parent closed synchronisation channel") } - if procSync != procRun { + if procSync.Type != procRun { return fmt.Errorf("invalid synchronisation flag from parent") } } diff --git a/libcontainer/process_linux.go b/libcontainer/process_linux.go index 1a6dc124..ac457c26 100644 --- a/libcontainer/process_linux.go +++ b/libcontainer/process_linux.go @@ -16,6 +16,7 @@ import ( "github.com/opencontainers/runc/libcontainer/cgroups" "github.com/opencontainers/runc/libcontainer/configs" "github.com/opencontainers/runc/libcontainer/system" + "github.com/opencontainers/runc/libcontainer/utils" ) type parentProcess interface { @@ -84,7 +85,7 @@ func (p *setnsProcess) start() (err error) { return newSystemError(err) } } - if err := json.NewEncoder(p.parentPipe).Encode(p.config); err != nil { + if err := utils.WriteJSON(p.parentPipe, p.config); err != nil { return newSystemError(err) } @@ -231,9 +232,8 @@ func (p *initProcess) start() (err error) { if err := p.sendConfig(); err != nil { return newSystemError(err) } - var ( - procSync syncType + procSync syncT sentRun bool ierr *genericError ) @@ -246,8 +246,7 @@ loop: } return newSystemError(err) } - - switch procSync { + switch procSync.Type { case procStart: break loop case procReady: @@ -255,7 +254,7 @@ loop: return newSystemError(err) } // Sync with child. - if err := json.NewEncoder(p.parentPipe).Encode(procRun); err != nil { + if err := utils.WriteJSON(p.parentPipe, syncT{procRun}); err != nil { return newSystemError(err) } sentRun = true @@ -317,10 +316,7 @@ func (p *initProcess) startTime() (string, error) { func (p *initProcess) sendConfig() error { // send the state to the container's init process then shutdown writes for the parent - if err := json.NewEncoder(p.parentPipe).Encode(p.config); err != nil { - return err - } - return nil + return utils.WriteJSON(p.parentPipe, p.config) } func (p *initProcess) createNetworkInterfaces() error { diff --git a/libcontainer/utils/utils.go b/libcontainer/utils/utils.go index 86cf1d65..1378006b 100644 --- a/libcontainer/utils/utils.go +++ b/libcontainer/utils/utils.go @@ -3,6 +3,7 @@ package utils import ( "crypto/rand" "encoding/hex" + "encoding/json" "io" "path/filepath" "syscall" @@ -36,10 +37,20 @@ func ResolveRootfs(uncleanRootfs string) (string, error) { } // ExitStatus returns the correct exit status for a process based on if it -// was signaled or exited cleanly. +// was signaled or exited cleanly func ExitStatus(status syscall.WaitStatus) int { if status.Signaled() { return exitSignalOffset + int(status.Signal()) } return status.ExitStatus() } + +// WriteJSON writes the provided struct v to w using standard json marshaling +func WriteJSON(w io.Writer, v interface{}) error { + data, err := json.Marshal(v) + if err != nil { + return err + } + _, err = w.Write(data) + return err +}