Skip to content

Commit 9d7831e

Browse files
author
Mrunal Patel
authored
Merge pull request #930 from hqhq/fix_state_detection
Make state detection precise
2 parents 0b5d51c + 14e95b2 commit 9d7831e

File tree

2 files changed

+56
-26
lines changed

2 files changed

+56
-26
lines changed

libcontainer/container_linux.go

Lines changed: 46 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import (
2222
"github.com/opencontainers/runc/libcontainer/cgroups"
2323
"github.com/opencontainers/runc/libcontainer/configs"
2424
"github.com/opencontainers/runc/libcontainer/criurpc"
25+
"github.com/opencontainers/runc/libcontainer/system"
2526
"github.com/opencontainers/runc/libcontainer/utils"
2627
"github.com/syndtr/gocapability/capability"
2728
"github.com/vishvananda/netlink/nl"
@@ -30,18 +31,19 @@ import (
3031
const stdioFdCount = 3
3132

3233
type linuxContainer struct {
33-
id string
34-
root string
35-
config *configs.Config
36-
cgroupManager cgroups.Manager
37-
initPath string
38-
initArgs []string
39-
initProcess parentProcess
40-
criuPath string
41-
m sync.Mutex
42-
criuVersion int
43-
state containerState
44-
created time.Time
34+
id string
35+
root string
36+
config *configs.Config
37+
cgroupManager cgroups.Manager
38+
initPath string
39+
initArgs []string
40+
initProcess parentProcess
41+
initProcessStartTime string
42+
criuPath string
43+
m sync.Mutex
44+
criuVersion int
45+
state containerState
46+
created time.Time
4547
}
4648

4749
// State represents a running container's state
@@ -252,9 +254,12 @@ func (c *linuxContainer) start(process *Process, isInit bool) error {
252254
c.state = &createdState{
253255
c: c,
254256
}
255-
if err := c.updateState(parent); err != nil {
257+
state, err := c.updateState(parent)
258+
if err != nil {
256259
return err
257260
}
261+
c.initProcessStartTime = state.InitProcessStartTime
262+
258263
if c.config.Hooks != nil {
259264
s := configs.HookState{
260265
Version: c.config.Version,
@@ -1043,7 +1048,7 @@ func (c *linuxContainer) criuNotifications(resp *criurpc.CriuResp, process *Proc
10431048
}); err != nil {
10441049
return err
10451050
}
1046-
if err := c.updateState(r); err != nil {
1051+
if _, err := c.updateState(r); err != nil {
10471052
return err
10481053
}
10491054
if err := os.Remove(filepath.Join(c.root, "checkpoint")); err != nil {
@@ -1055,13 +1060,17 @@ func (c *linuxContainer) criuNotifications(resp *criurpc.CriuResp, process *Proc
10551060
return nil
10561061
}
10571062

1058-
func (c *linuxContainer) updateState(process parentProcess) error {
1063+
func (c *linuxContainer) updateState(process parentProcess) (*State, error) {
10591064
c.initProcess = process
10601065
state, err := c.currentState()
10611066
if err != nil {
1062-
return err
1067+
return nil, err
1068+
}
1069+
err = c.saveState(state)
1070+
if err != nil {
1071+
return nil, err
10631072
}
1064-
return c.saveState(state)
1073+
return state, nil
10651074
}
10661075

10671076
func (c *linuxContainer) saveState(s *State) error {
@@ -1109,6 +1118,21 @@ func (c *linuxContainer) refreshState() error {
11091118
return c.state.transition(&stoppedState{c: c})
11101119
}
11111120

1121+
// doesInitProcessExist checks if the init process is still the same process
1122+
// as the initial one, it could happen that the original process has exited
1123+
// and a new process has been created with the same pid, in this case, the
1124+
// container would already be stopped.
1125+
func (c *linuxContainer) doesInitProcessExist(initPid int) (bool, error) {
1126+
startTime, err := system.GetProcessStartTime(initPid)
1127+
if err != nil {
1128+
return false, newSystemErrorWithCausef(err, "getting init process %d start time", initPid)
1129+
}
1130+
if c.initProcessStartTime != startTime {
1131+
return false, nil
1132+
}
1133+
return true, nil
1134+
}
1135+
11121136
func (c *linuxContainer) runType() (Status, error) {
11131137
if c.initProcess == nil {
11141138
return Stopped, nil
@@ -1124,6 +1148,11 @@ func (c *linuxContainer) runType() (Status, error) {
11241148
}
11251149
return Stopped, newSystemErrorWithCausef(err, "sending signal 0 to pid %d", pid)
11261150
}
1151+
// check if the process is still the original init process.
1152+
exist, err := c.doesInitProcessExist(pid)
1153+
if !exist || err != nil {
1154+
return Stopped, err
1155+
}
11271156
// check if the process that is running is the init process or the user's process.
11281157
// this is the difference between the container Running and Created.
11291158
environ, err := ioutil.ReadFile(fmt.Sprintf("/proc/%d/environ", pid))

libcontainer/factory_linux.go

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -217,15 +217,16 @@ func (l *LinuxFactory) Load(id string) (Container, error) {
217217
fds: state.ExternalDescriptors,
218218
}
219219
c := &linuxContainer{
220-
initProcess: r,
221-
id: id,
222-
config: &state.Config,
223-
initPath: l.InitPath,
224-
initArgs: l.InitArgs,
225-
criuPath: l.CriuPath,
226-
cgroupManager: l.NewCgroupsManager(state.Config.Cgroups, state.CgroupPaths),
227-
root: containerRoot,
228-
created: state.Created,
220+
initProcess: r,
221+
initProcessStartTime: state.InitProcessStartTime,
222+
id: id,
223+
config: &state.Config,
224+
initPath: l.InitPath,
225+
initArgs: l.InitArgs,
226+
criuPath: l.CriuPath,
227+
cgroupManager: l.NewCgroupsManager(state.Config.Cgroups, state.CgroupPaths),
228+
root: containerRoot,
229+
created: state.Created,
229230
}
230231
c.state = &loadedState{c: c}
231232
if err := c.refreshState(); err != nil {

0 commit comments

Comments
 (0)