From ba0246da75b0bb2c52dbaf9bcc338694f18e0ed0 Mon Sep 17 00:00:00 2001 From: Wei Fu Date: Mon, 7 Sep 2020 15:04:04 +0800 Subject: [PATCH] libcontainer: Store state.json before sync procRun If the procRun state has been synced and the runc-create process has been killed for some reason, the runc-init[2:stage] process will be leaky. And the runc command also fails to parse root directory because the container doesn't have state.json. In order to make it possible to clean the leaky runc-init[2:stage] process , we should store the status before sync procRun. ```before current workflow: [ child ] <-> [ parent ] procHooks --> [run hooks] <-- procResume procReady --> [final setup] <-- procRun ( killed for some reason) ( store state.json ) ``` ```expected expected workflow: [ child ] <-> [ parent ] procHooks --> [run hooks] <-- procResume procReady --> [final setup] store state.json <-- procRun ``` Signed-off-by: Wei Fu --- libcontainer/container_linux.go | 12 +----------- libcontainer/process_linux.go | 23 +++++++++++++++++++++++ 2 files changed, 24 insertions(+), 11 deletions(-) diff --git a/libcontainer/container_linux.go b/libcontainer/container_linux.go index ee08c17e53c..3531487c641 100644 --- a/libcontainer/container_linux.go +++ b/libcontainer/container_linux.go @@ -369,18 +369,8 @@ func (c *linuxContainer) start(process *Process) error { } return newSystemErrorWithCause(err, "starting container process") } - // generate a timestamp indicating when the container was started - c.created = time.Now().UTC() - if process.Init { - c.state = &createdState{ - c: c, - } - state, err := c.updateState(parent) - if err != nil { - return err - } - c.initProcessStartTime = state.InitProcessStartTime + if process.Init { if c.config.Hooks != nil { s, err := c.currentOCIState() if err != nil { diff --git a/libcontainer/process_linux.go b/libcontainer/process_linux.go index cb8c724a206..2365d4e0f29 100644 --- a/libcontainer/process_linux.go +++ b/libcontainer/process_linux.go @@ -11,6 +11,7 @@ import ( "os/exec" "path/filepath" "strconv" + "time" "github.com/opencontainers/runc/libcontainer/cgroups" "github.com/opencontainers/runc/libcontainer/cgroups/fs2" @@ -411,6 +412,28 @@ func (p *initProcess) start() (retErr error) { } } } + + // generate a timestamp indicating when the container was started + p.container.created = time.Now().UTC() + p.container.state = &createdState{ + c: p.container, + } + + // NOTE: If the procRun state has been synced and the + // runc-create process has been killed for some reason, + // the runc-init[2:stage] process will be leaky. And + // the runc command also fails to parse root directory + // because the container doesn't have state.json. + // + // In order to cleanup the runc-init[2:stage] by + // runc-delete/stop, we should store the status before + // procRun sync. + state, uerr := p.container.updateState(p) + if uerr != nil { + return newSystemErrorWithCause(err, "store init state") + } + p.container.initProcessStartTime = state.InitProcessStartTime + // Sync with child. if err := writeSync(p.messageSockPair.parent, procRun); err != nil { return newSystemErrorWithCause(err, "writing syncT 'run'")