Fix signal handling for unit tests
Signed-off-by: Michael Crosby <crosbymichael@gmail.com>
This commit is contained in:
parent
60f5df6e09
commit
efcd73fb5b
2
Makefile
2
Makefile
|
@ -55,7 +55,7 @@ unittest: runctestimage
|
||||||
docker run -e TESTFLAGS -ti --privileged --rm -v $(CURDIR):/go/src/$(PROJECT) $(RUNC_TEST_IMAGE) make localunittest
|
docker run -e TESTFLAGS -ti --privileged --rm -v $(CURDIR):/go/src/$(PROJECT) $(RUNC_TEST_IMAGE) make localunittest
|
||||||
|
|
||||||
localunittest: all
|
localunittest: all
|
||||||
go test -tags "$(BUILDTAGS)" ${TESTFLAGS} -v ./...
|
go test -timeout 3m -tags "$(BUILDTAGS)" ${TESTFLAGS} -v ./...
|
||||||
|
|
||||||
integration: runctestimage
|
integration: runctestimage
|
||||||
docker run -e TESTFLAGS -t --privileged --rm -v $(CURDIR):/go/src/$(PROJECT) $(RUNC_TEST_IMAGE) make localintegration
|
docker run -e TESTFLAGS -t --privileged --rm -v $(CURDIR):/go/src/$(PROJECT) $(RUNC_TEST_IMAGE) make localintegration
|
||||||
|
|
|
@ -17,16 +17,12 @@ type Status int
|
||||||
const (
|
const (
|
||||||
// Created is the status that denotes the container exists but has not been run yet.
|
// Created is the status that denotes the container exists but has not been run yet.
|
||||||
Created Status = iota
|
Created Status = iota
|
||||||
|
|
||||||
// Running is the status that denotes the container exists and is running.
|
// Running is the status that denotes the container exists and is running.
|
||||||
Running
|
Running
|
||||||
|
|
||||||
// Pausing is the status that denotes the container exists, it is in the process of being paused.
|
// Pausing is the status that denotes the container exists, it is in the process of being paused.
|
||||||
Pausing
|
Pausing
|
||||||
|
|
||||||
// Paused is the status that denotes the container exists, but all its processes are paused.
|
// Paused is the status that denotes the container exists, but all its processes are paused.
|
||||||
Paused
|
Paused
|
||||||
|
|
||||||
// Stopped is the status that denotes the container does not have a created or running process.
|
// Stopped is the status that denotes the container does not have a created or running process.
|
||||||
Stopped
|
Stopped
|
||||||
)
|
)
|
||||||
|
@ -127,6 +123,17 @@ type BaseContainer interface {
|
||||||
// Systemerror - System error.
|
// Systemerror - System error.
|
||||||
Start(process *Process) (err error)
|
Start(process *Process) (err error)
|
||||||
|
|
||||||
|
// StartI immediatly starts the process inside the conatiner. Returns error if process
|
||||||
|
// fails to start. It does not block waiting for a SIGCONT after start returns but
|
||||||
|
// sends the signal when the process has completed.
|
||||||
|
//
|
||||||
|
// errors:
|
||||||
|
// ContainerDestroyed - Container no longer exists,
|
||||||
|
// ConfigInvalid - config is invalid,
|
||||||
|
// ContainerPaused - Container is paused,
|
||||||
|
// Systemerror - System error.
|
||||||
|
StartI(process *Process) (err error)
|
||||||
|
|
||||||
// Destroys the container after killing all running processes.
|
// Destroys the container after killing all running processes.
|
||||||
//
|
//
|
||||||
// Any event registrations are removed before the container is destroyed.
|
// Any event registrations are removed before the container is destroyed.
|
||||||
|
|
|
@ -29,6 +29,10 @@ import (
|
||||||
|
|
||||||
const stdioFdCount = 3
|
const stdioFdCount = 3
|
||||||
|
|
||||||
|
// InitContinueSignal is used to signal the container init process to
|
||||||
|
// start the users specified process after the container create has finished.
|
||||||
|
const InitContinueSignal = syscall.SIGCONT
|
||||||
|
|
||||||
type linuxContainer struct {
|
type linuxContainer struct {
|
||||||
id string
|
id string
|
||||||
root string
|
root string
|
||||||
|
@ -181,8 +185,28 @@ func (c *linuxContainer) Start(process *Process) error {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
doInit := status == Stopped
|
return c.start(process, status == Stopped)
|
||||||
parent, err := c.newParentProcess(process, doInit)
|
}
|
||||||
|
|
||||||
|
func (c *linuxContainer) StartI(process *Process) error {
|
||||||
|
c.m.Lock()
|
||||||
|
defer c.m.Unlock()
|
||||||
|
status, err := c.currentStatus()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
isInit := status == Stopped
|
||||||
|
if err := c.start(process, isInit); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if isInit {
|
||||||
|
return process.ops.signal(InitContinueSignal)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *linuxContainer) start(process *Process, isInit bool) error {
|
||||||
|
parent, err := c.newParentProcess(process, isInit)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return newSystemErrorWithCause(err, "creating new parent process")
|
return newSystemErrorWithCause(err, "creating new parent process")
|
||||||
}
|
}
|
||||||
|
@ -198,7 +222,10 @@ func (c *linuxContainer) Start(process *Process) error {
|
||||||
c.state = &runningState{
|
c.state = &runningState{
|
||||||
c: c,
|
c: c,
|
||||||
}
|
}
|
||||||
if doInit {
|
if isInit {
|
||||||
|
c.state = &createdState{
|
||||||
|
c: c,
|
||||||
|
}
|
||||||
if err := c.updateState(parent); err != nil {
|
if err := c.updateState(parent); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -370,9 +397,8 @@ func (c *linuxContainer) Pause() error {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if status != Running {
|
switch status {
|
||||||
return newGenericError(fmt.Errorf("container not running"), ContainerNotRunning)
|
case Running, Created:
|
||||||
}
|
|
||||||
if err := c.cgroupManager.Freeze(configs.Frozen); err != nil {
|
if err := c.cgroupManager.Freeze(configs.Frozen); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -380,6 +406,8 @@ func (c *linuxContainer) Pause() error {
|
||||||
c: c,
|
c: c,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
return newGenericError(fmt.Errorf("container not running: %s", status), ContainerNotRunning)
|
||||||
|
}
|
||||||
|
|
||||||
func (c *linuxContainer) Resume() error {
|
func (c *linuxContainer) Resume() error {
|
||||||
c.m.Lock()
|
c.m.Lock()
|
||||||
|
|
|
@ -222,7 +222,7 @@ func (l *LinuxFactory) Type() string {
|
||||||
func (l *LinuxFactory) StartInitialization() (err error) {
|
func (l *LinuxFactory) StartInitialization() (err error) {
|
||||||
// start the signal handler as soon as we can
|
// start the signal handler as soon as we can
|
||||||
s := make(chan os.Signal, 1)
|
s := make(chan os.Signal, 1)
|
||||||
signal.Notify(s, syscall.SIGCONT)
|
signal.Notify(s, InitContinueSignal)
|
||||||
fdStr := os.Getenv("_LIBCONTAINER_INITPIPE")
|
fdStr := os.Getenv("_LIBCONTAINER_INITPIPE")
|
||||||
pipefd, err := strconv.Atoi(fdStr)
|
pipefd, err := strconv.Atoi(fdStr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -89,7 +89,7 @@ func TestCheckpoint(t *testing.T) {
|
||||||
Stdout: &stdout,
|
Stdout: &stdout,
|
||||||
}
|
}
|
||||||
|
|
||||||
err = container.Start(&pconfig)
|
err = container.StartI(&pconfig)
|
||||||
stdinR.Close()
|
stdinR.Close()
|
||||||
defer stdinW.Close()
|
defer stdinW.Close()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -241,7 +241,7 @@ func TestEnter(t *testing.T) {
|
||||||
Stdin: stdinR,
|
Stdin: stdinR,
|
||||||
Stdout: &stdout,
|
Stdout: &stdout,
|
||||||
}
|
}
|
||||||
err = container.Start(&pconfig)
|
err = container.StartI(&pconfig)
|
||||||
stdinR.Close()
|
stdinR.Close()
|
||||||
defer stdinW.Close()
|
defer stdinW.Close()
|
||||||
ok(t, err)
|
ok(t, err)
|
||||||
|
@ -259,7 +259,7 @@ func TestEnter(t *testing.T) {
|
||||||
pconfig2.Stdin = stdinR2
|
pconfig2.Stdin = stdinR2
|
||||||
pconfig2.Stdout = &stdout2
|
pconfig2.Stdout = &stdout2
|
||||||
|
|
||||||
err = container.Start(&pconfig2)
|
err = container.StartI(&pconfig2)
|
||||||
stdinR2.Close()
|
stdinR2.Close()
|
||||||
defer stdinW2.Close()
|
defer stdinW2.Close()
|
||||||
ok(t, err)
|
ok(t, err)
|
||||||
|
@ -330,7 +330,7 @@ func TestProcessEnv(t *testing.T) {
|
||||||
Stdin: nil,
|
Stdin: nil,
|
||||||
Stdout: &stdout,
|
Stdout: &stdout,
|
||||||
}
|
}
|
||||||
err = container.Start(&pconfig)
|
err = container.StartI(&pconfig)
|
||||||
ok(t, err)
|
ok(t, err)
|
||||||
|
|
||||||
// Wait for process
|
// Wait for process
|
||||||
|
@ -378,7 +378,7 @@ func TestProcessCaps(t *testing.T) {
|
||||||
Stdin: nil,
|
Stdin: nil,
|
||||||
Stdout: &stdout,
|
Stdout: &stdout,
|
||||||
}
|
}
|
||||||
err = container.Start(&pconfig)
|
err = container.StartI(&pconfig)
|
||||||
ok(t, err)
|
ok(t, err)
|
||||||
|
|
||||||
// Wait for process
|
// Wait for process
|
||||||
|
@ -448,7 +448,7 @@ func TestAdditionalGroups(t *testing.T) {
|
||||||
Stdin: nil,
|
Stdin: nil,
|
||||||
Stdout: &stdout,
|
Stdout: &stdout,
|
||||||
}
|
}
|
||||||
err = container.Start(&pconfig)
|
err = container.StartI(&pconfig)
|
||||||
ok(t, err)
|
ok(t, err)
|
||||||
|
|
||||||
// Wait for process
|
// Wait for process
|
||||||
|
@ -508,7 +508,7 @@ func testFreeze(t *testing.T, systemd bool) {
|
||||||
Env: standardEnvironment,
|
Env: standardEnvironment,
|
||||||
Stdin: stdinR,
|
Stdin: stdinR,
|
||||||
}
|
}
|
||||||
err = container.Start(pconfig)
|
err = container.StartI(pconfig)
|
||||||
stdinR.Close()
|
stdinR.Close()
|
||||||
defer stdinW.Close()
|
defer stdinW.Close()
|
||||||
ok(t, err)
|
ok(t, err)
|
||||||
|
@ -719,7 +719,7 @@ func TestContainerState(t *testing.T) {
|
||||||
Env: standardEnvironment,
|
Env: standardEnvironment,
|
||||||
Stdin: stdinR,
|
Stdin: stdinR,
|
||||||
}
|
}
|
||||||
err = container.Start(p)
|
err = container.StartI(p)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
@ -772,7 +772,7 @@ func TestPassExtraFiles(t *testing.T) {
|
||||||
Stdin: nil,
|
Stdin: nil,
|
||||||
Stdout: &stdout,
|
Stdout: &stdout,
|
||||||
}
|
}
|
||||||
err = container.Start(&process)
|
err = container.StartI(&process)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
@ -853,7 +853,7 @@ func TestMountCmds(t *testing.T) {
|
||||||
Args: []string{"sh", "-c", "env"},
|
Args: []string{"sh", "-c", "env"},
|
||||||
Env: standardEnvironment,
|
Env: standardEnvironment,
|
||||||
}
|
}
|
||||||
err = container.Start(&pconfig)
|
err = container.StartI(&pconfig)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
@ -902,7 +902,7 @@ func TestSysctl(t *testing.T) {
|
||||||
Stdin: nil,
|
Stdin: nil,
|
||||||
Stdout: &stdout,
|
Stdout: &stdout,
|
||||||
}
|
}
|
||||||
err = container.Start(&pconfig)
|
err = container.StartI(&pconfig)
|
||||||
ok(t, err)
|
ok(t, err)
|
||||||
|
|
||||||
// Wait for process
|
// Wait for process
|
||||||
|
@ -1042,7 +1042,7 @@ func TestOomScoreAdj(t *testing.T) {
|
||||||
Stdin: nil,
|
Stdin: nil,
|
||||||
Stdout: &stdout,
|
Stdout: &stdout,
|
||||||
}
|
}
|
||||||
err = container.Start(&pconfig)
|
err = container.StartI(&pconfig)
|
||||||
ok(t, err)
|
ok(t, err)
|
||||||
|
|
||||||
// Wait for process
|
// Wait for process
|
||||||
|
@ -1114,7 +1114,7 @@ func TestHook(t *testing.T) {
|
||||||
Stdin: nil,
|
Stdin: nil,
|
||||||
Stdout: &stdout,
|
Stdout: &stdout,
|
||||||
}
|
}
|
||||||
err = container.Start(&pconfig)
|
err = container.StartI(&pconfig)
|
||||||
ok(t, err)
|
ok(t, err)
|
||||||
|
|
||||||
// Wait for process
|
// Wait for process
|
||||||
|
@ -1231,7 +1231,7 @@ func TestRootfsPropagationSlaveMount(t *testing.T) {
|
||||||
Stdin: stdinR,
|
Stdin: stdinR,
|
||||||
}
|
}
|
||||||
|
|
||||||
err = container.Start(pconfig)
|
err = container.StartI(pconfig)
|
||||||
stdinR.Close()
|
stdinR.Close()
|
||||||
defer stdinW.Close()
|
defer stdinW.Close()
|
||||||
ok(t, err)
|
ok(t, err)
|
||||||
|
@ -1260,7 +1260,7 @@ func TestRootfsPropagationSlaveMount(t *testing.T) {
|
||||||
Stdout: &stdout2,
|
Stdout: &stdout2,
|
||||||
}
|
}
|
||||||
|
|
||||||
err = container.Start(pconfig2)
|
err = container.StartI(pconfig2)
|
||||||
stdinR2.Close()
|
stdinR2.Close()
|
||||||
defer stdinW2.Close()
|
defer stdinW2.Close()
|
||||||
ok(t, err)
|
ok(t, err)
|
||||||
|
@ -1348,7 +1348,7 @@ func TestRootfsPropagationSharedMount(t *testing.T) {
|
||||||
Stdin: stdinR,
|
Stdin: stdinR,
|
||||||
}
|
}
|
||||||
|
|
||||||
err = container.Start(pconfig)
|
err = container.StartI(pconfig)
|
||||||
stdinR.Close()
|
stdinR.Close()
|
||||||
defer stdinW.Close()
|
defer stdinW.Close()
|
||||||
ok(t, err)
|
ok(t, err)
|
||||||
|
@ -1380,7 +1380,7 @@ func TestRootfsPropagationSharedMount(t *testing.T) {
|
||||||
Capabilities: processCaps,
|
Capabilities: processCaps,
|
||||||
}
|
}
|
||||||
|
|
||||||
err = container.Start(pconfig2)
|
err = container.StartI(pconfig2)
|
||||||
stdinR2.Close()
|
stdinR2.Close()
|
||||||
defer stdinW2.Close()
|
defer stdinW2.Close()
|
||||||
ok(t, err)
|
ok(t, err)
|
||||||
|
@ -1452,7 +1452,7 @@ func TestInitJoinPID(t *testing.T) {
|
||||||
Env: standardEnvironment,
|
Env: standardEnvironment,
|
||||||
Stdin: stdinR1,
|
Stdin: stdinR1,
|
||||||
}
|
}
|
||||||
err = container1.Start(init1)
|
err = container1.StartI(init1)
|
||||||
stdinR1.Close()
|
stdinR1.Close()
|
||||||
defer stdinW1.Close()
|
defer stdinW1.Close()
|
||||||
ok(t, err)
|
ok(t, err)
|
||||||
|
@ -1462,7 +1462,7 @@ func TestInitJoinPID(t *testing.T) {
|
||||||
ok(t, err)
|
ok(t, err)
|
||||||
pidns1 := state1.NamespacePaths[configs.NEWPID]
|
pidns1 := state1.NamespacePaths[configs.NEWPID]
|
||||||
|
|
||||||
// Start a container inside the existing pidns but with different cgroups
|
// StartI a container inside the existing pidns but with different cgroups
|
||||||
config2 := newTemplateConfig(rootfs)
|
config2 := newTemplateConfig(rootfs)
|
||||||
config2.Namespaces.Add(configs.NEWPID, pidns1)
|
config2.Namespaces.Add(configs.NEWPID, pidns1)
|
||||||
config2.Cgroups.Path = "integration/test2"
|
config2.Cgroups.Path = "integration/test2"
|
||||||
|
@ -1478,7 +1478,7 @@ func TestInitJoinPID(t *testing.T) {
|
||||||
Env: standardEnvironment,
|
Env: standardEnvironment,
|
||||||
Stdin: stdinR2,
|
Stdin: stdinR2,
|
||||||
}
|
}
|
||||||
err = container2.Start(init2)
|
err = container2.StartI(init2)
|
||||||
stdinR2.Close()
|
stdinR2.Close()
|
||||||
defer stdinW2.Close()
|
defer stdinW2.Close()
|
||||||
ok(t, err)
|
ok(t, err)
|
||||||
|
@ -1508,7 +1508,7 @@ func TestInitJoinPID(t *testing.T) {
|
||||||
Env: standardEnvironment,
|
Env: standardEnvironment,
|
||||||
Stdout: buffers.Stdout,
|
Stdout: buffers.Stdout,
|
||||||
}
|
}
|
||||||
err = container1.Start(ps)
|
err = container1.StartI(ps)
|
||||||
ok(t, err)
|
ok(t, err)
|
||||||
waitProcess(ps, t)
|
waitProcess(ps, t)
|
||||||
|
|
||||||
|
@ -1557,7 +1557,7 @@ func TestInitJoinNetworkAndUser(t *testing.T) {
|
||||||
Env: standardEnvironment,
|
Env: standardEnvironment,
|
||||||
Stdin: stdinR1,
|
Stdin: stdinR1,
|
||||||
}
|
}
|
||||||
err = container1.Start(init1)
|
err = container1.StartI(init1)
|
||||||
stdinR1.Close()
|
stdinR1.Close()
|
||||||
defer stdinW1.Close()
|
defer stdinW1.Close()
|
||||||
ok(t, err)
|
ok(t, err)
|
||||||
|
@ -1568,7 +1568,7 @@ func TestInitJoinNetworkAndUser(t *testing.T) {
|
||||||
netns1 := state1.NamespacePaths[configs.NEWNET]
|
netns1 := state1.NamespacePaths[configs.NEWNET]
|
||||||
userns1 := state1.NamespacePaths[configs.NEWUSER]
|
userns1 := state1.NamespacePaths[configs.NEWUSER]
|
||||||
|
|
||||||
// Start a container inside the existing pidns but with different cgroups
|
// StartI a container inside the existing pidns but with different cgroups
|
||||||
rootfs2, err := newRootfs()
|
rootfs2, err := newRootfs()
|
||||||
ok(t, err)
|
ok(t, err)
|
||||||
defer remove(rootfs2)
|
defer remove(rootfs2)
|
||||||
|
@ -1591,7 +1591,7 @@ func TestInitJoinNetworkAndUser(t *testing.T) {
|
||||||
Env: standardEnvironment,
|
Env: standardEnvironment,
|
||||||
Stdin: stdinR2,
|
Stdin: stdinR2,
|
||||||
}
|
}
|
||||||
err = container2.Start(init2)
|
err = container2.StartI(init2)
|
||||||
stdinR2.Close()
|
stdinR2.Close()
|
||||||
defer stdinW2.Close()
|
defer stdinW2.Close()
|
||||||
ok(t, err)
|
ok(t, err)
|
||||||
|
|
|
@ -36,7 +36,7 @@ func TestExecIn(t *testing.T) {
|
||||||
Env: standardEnvironment,
|
Env: standardEnvironment,
|
||||||
Stdin: stdinR,
|
Stdin: stdinR,
|
||||||
}
|
}
|
||||||
err = container.Start(process)
|
err = container.StartI(process)
|
||||||
stdinR.Close()
|
stdinR.Close()
|
||||||
defer stdinW.Close()
|
defer stdinW.Close()
|
||||||
ok(t, err)
|
ok(t, err)
|
||||||
|
@ -51,7 +51,7 @@ func TestExecIn(t *testing.T) {
|
||||||
Stderr: buffers.Stderr,
|
Stderr: buffers.Stderr,
|
||||||
}
|
}
|
||||||
|
|
||||||
err = container.Start(ps)
|
err = container.StartI(ps)
|
||||||
ok(t, err)
|
ok(t, err)
|
||||||
waitProcess(ps, t)
|
waitProcess(ps, t)
|
||||||
stdinW.Close()
|
stdinW.Close()
|
||||||
|
@ -103,7 +103,7 @@ func testExecInRlimit(t *testing.T, userns bool) {
|
||||||
Env: standardEnvironment,
|
Env: standardEnvironment,
|
||||||
Stdin: stdinR,
|
Stdin: stdinR,
|
||||||
}
|
}
|
||||||
err = container.Start(process)
|
err = container.StartI(process)
|
||||||
stdinR.Close()
|
stdinR.Close()
|
||||||
defer stdinW.Close()
|
defer stdinW.Close()
|
||||||
ok(t, err)
|
ok(t, err)
|
||||||
|
@ -121,7 +121,7 @@ func testExecInRlimit(t *testing.T, userns bool) {
|
||||||
{Type: syscall.RLIMIT_NOFILE, Hard: 1026, Soft: 1026},
|
{Type: syscall.RLIMIT_NOFILE, Hard: 1026, Soft: 1026},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
err = container.Start(ps)
|
err = container.StartI(ps)
|
||||||
ok(t, err)
|
ok(t, err)
|
||||||
waitProcess(ps, t)
|
waitProcess(ps, t)
|
||||||
|
|
||||||
|
@ -155,7 +155,7 @@ func TestExecInError(t *testing.T) {
|
||||||
Env: standardEnvironment,
|
Env: standardEnvironment,
|
||||||
Stdin: stdinR,
|
Stdin: stdinR,
|
||||||
}
|
}
|
||||||
err = container.Start(process)
|
err = container.StartI(process)
|
||||||
stdinR.Close()
|
stdinR.Close()
|
||||||
defer func() {
|
defer func() {
|
||||||
stdinW.Close()
|
stdinW.Close()
|
||||||
|
@ -173,7 +173,7 @@ func TestExecInError(t *testing.T) {
|
||||||
Env: standardEnvironment,
|
Env: standardEnvironment,
|
||||||
Stdout: &out,
|
Stdout: &out,
|
||||||
}
|
}
|
||||||
err = container.Start(unexistent)
|
err = container.StartI(unexistent)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
t.Fatal("Should be an error")
|
t.Fatal("Should be an error")
|
||||||
}
|
}
|
||||||
|
@ -207,7 +207,7 @@ func TestExecInTTY(t *testing.T) {
|
||||||
Env: standardEnvironment,
|
Env: standardEnvironment,
|
||||||
Stdin: stdinR,
|
Stdin: stdinR,
|
||||||
}
|
}
|
||||||
err = container.Start(process)
|
err = container.StartI(process)
|
||||||
stdinR.Close()
|
stdinR.Close()
|
||||||
defer stdinW.Close()
|
defer stdinW.Close()
|
||||||
ok(t, err)
|
ok(t, err)
|
||||||
|
@ -225,7 +225,7 @@ func TestExecInTTY(t *testing.T) {
|
||||||
close(copy)
|
close(copy)
|
||||||
}()
|
}()
|
||||||
ok(t, err)
|
ok(t, err)
|
||||||
err = container.Start(ps)
|
err = container.StartI(ps)
|
||||||
ok(t, err)
|
ok(t, err)
|
||||||
select {
|
select {
|
||||||
case <-time.After(5 * time.Second):
|
case <-time.After(5 * time.Second):
|
||||||
|
@ -264,7 +264,7 @@ func TestExecInEnvironment(t *testing.T) {
|
||||||
Env: standardEnvironment,
|
Env: standardEnvironment,
|
||||||
Stdin: stdinR,
|
Stdin: stdinR,
|
||||||
}
|
}
|
||||||
err = container.Start(process)
|
err = container.StartI(process)
|
||||||
stdinR.Close()
|
stdinR.Close()
|
||||||
defer stdinW.Close()
|
defer stdinW.Close()
|
||||||
ok(t, err)
|
ok(t, err)
|
||||||
|
@ -283,7 +283,7 @@ func TestExecInEnvironment(t *testing.T) {
|
||||||
Stdout: buffers.Stdout,
|
Stdout: buffers.Stdout,
|
||||||
Stderr: buffers.Stderr,
|
Stderr: buffers.Stderr,
|
||||||
}
|
}
|
||||||
err = container.Start(process2)
|
err = container.StartI(process2)
|
||||||
ok(t, err)
|
ok(t, err)
|
||||||
waitProcess(process2, t)
|
waitProcess(process2, t)
|
||||||
|
|
||||||
|
@ -328,7 +328,7 @@ func TestExecinPassExtraFiles(t *testing.T) {
|
||||||
Env: standardEnvironment,
|
Env: standardEnvironment,
|
||||||
Stdin: stdinR,
|
Stdin: stdinR,
|
||||||
}
|
}
|
||||||
err = container.Start(process)
|
err = container.StartI(process)
|
||||||
stdinR.Close()
|
stdinR.Close()
|
||||||
defer stdinW.Close()
|
defer stdinW.Close()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -346,7 +346,7 @@ func TestExecinPassExtraFiles(t *testing.T) {
|
||||||
Stdin: nil,
|
Stdin: nil,
|
||||||
Stdout: &stdout,
|
Stdout: &stdout,
|
||||||
}
|
}
|
||||||
err = container.Start(inprocess)
|
err = container.StartI(inprocess)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
@ -401,7 +401,7 @@ func TestExecInOomScoreAdj(t *testing.T) {
|
||||||
Env: standardEnvironment,
|
Env: standardEnvironment,
|
||||||
Stdin: stdinR,
|
Stdin: stdinR,
|
||||||
}
|
}
|
||||||
err = container.Start(process)
|
err = container.StartI(process)
|
||||||
stdinR.Close()
|
stdinR.Close()
|
||||||
defer stdinW.Close()
|
defer stdinW.Close()
|
||||||
ok(t, err)
|
ok(t, err)
|
||||||
|
@ -415,7 +415,7 @@ func TestExecInOomScoreAdj(t *testing.T) {
|
||||||
Stdout: buffers.Stdout,
|
Stdout: buffers.Stdout,
|
||||||
Stderr: buffers.Stderr,
|
Stderr: buffers.Stderr,
|
||||||
}
|
}
|
||||||
err = container.Start(ps)
|
err = container.StartI(ps)
|
||||||
ok(t, err)
|
ok(t, err)
|
||||||
waitProcess(ps, t)
|
waitProcess(ps, t)
|
||||||
|
|
||||||
|
@ -456,7 +456,7 @@ func TestExecInUserns(t *testing.T) {
|
||||||
Env: standardEnvironment,
|
Env: standardEnvironment,
|
||||||
Stdin: stdinR,
|
Stdin: stdinR,
|
||||||
}
|
}
|
||||||
err = container.Start(process)
|
err = container.StartI(process)
|
||||||
stdinR.Close()
|
stdinR.Close()
|
||||||
defer stdinW.Close()
|
defer stdinW.Close()
|
||||||
ok(t, err)
|
ok(t, err)
|
||||||
|
@ -476,7 +476,7 @@ func TestExecInUserns(t *testing.T) {
|
||||||
Stdout: buffers.Stdout,
|
Stdout: buffers.Stdout,
|
||||||
Stderr: os.Stderr,
|
Stderr: os.Stderr,
|
||||||
}
|
}
|
||||||
err = container.Start(process2)
|
err = container.StartI(process2)
|
||||||
ok(t, err)
|
ok(t, err)
|
||||||
waitProcess(process2, t)
|
waitProcess(process2, t)
|
||||||
stdinW.Close()
|
stdinW.Close()
|
||||||
|
|
|
@ -50,7 +50,7 @@ func TestSeccompDenyGetcwd(t *testing.T) {
|
||||||
Stderr: buffers.Stderr,
|
Stderr: buffers.Stderr,
|
||||||
}
|
}
|
||||||
|
|
||||||
err = container.Start(pwd)
|
err = container.StartI(pwd)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
@ -125,7 +125,7 @@ func TestSeccompPermitWriteConditional(t *testing.T) {
|
||||||
Stderr: buffers.Stderr,
|
Stderr: buffers.Stderr,
|
||||||
}
|
}
|
||||||
|
|
||||||
err = container.Start(dmesg)
|
err = container.StartI(dmesg)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
@ -186,7 +186,7 @@ func TestSeccompDenyWriteConditional(t *testing.T) {
|
||||||
Stderr: buffers.Stderr,
|
Stderr: buffers.Stderr,
|
||||||
}
|
}
|
||||||
|
|
||||||
err = container.Start(dmesg)
|
err = container.StartI(dmesg)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
|
@ -89,12 +89,14 @@ func newTemplateConfig(rootfs string) *configs.Config {
|
||||||
Data: "mode=1777,size=65536k",
|
Data: "mode=1777,size=65536k",
|
||||||
Flags: defaultMountFlags,
|
Flags: defaultMountFlags,
|
||||||
},
|
},
|
||||||
|
/*
|
||||||
{
|
{
|
||||||
Source: "mqueue",
|
Source: "mqueue",
|
||||||
Destination: "/dev/mqueue",
|
Destination: "/dev/mqueue",
|
||||||
Device: "mqueue",
|
Device: "mqueue",
|
||||||
Flags: defaultMountFlags,
|
Flags: defaultMountFlags,
|
||||||
},
|
},
|
||||||
|
*/
|
||||||
{
|
{
|
||||||
Source: "sysfs",
|
Source: "sysfs",
|
||||||
Destination: "/sys",
|
Destination: "/sys",
|
||||||
|
|
|
@ -123,13 +123,10 @@ func runContainer(config *configs.Config, console string, args ...string) (buffe
|
||||||
Stderr: buffers.Stderr,
|
Stderr: buffers.Stderr,
|
||||||
}
|
}
|
||||||
|
|
||||||
err = container.Start(process)
|
err = container.StartI(process)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return buffers, -1, err
|
return buffers, -1, err
|
||||||
}
|
}
|
||||||
if err := container.Signal(syscall.SIGCONT); err != nil {
|
|
||||||
return buffers, -1, err
|
|
||||||
}
|
|
||||||
ps, err := process.Wait()
|
ps, err := process.Wait()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return buffers, -1, err
|
return buffers, -1, err
|
||||||
|
|
|
@ -221,6 +221,7 @@ func (p *initProcess) execSetns() error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
p.cmd.Process = process
|
p.cmd.Process = process
|
||||||
|
p.process.ops = p
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -6,6 +6,7 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
"syscall"
|
||||||
|
|
||||||
"github.com/Sirupsen/logrus"
|
"github.com/Sirupsen/logrus"
|
||||||
"github.com/opencontainers/runc/libcontainer/configs"
|
"github.com/opencontainers/runc/libcontainer/configs"
|
||||||
|
@ -149,8 +150,9 @@ func (i *createdState) status() Status {
|
||||||
|
|
||||||
func (i *createdState) transition(s containerState) error {
|
func (i *createdState) transition(s containerState) error {
|
||||||
switch s.(type) {
|
switch s.(type) {
|
||||||
case *runningState:
|
case *runningState, *pausedState, *stoppedState:
|
||||||
i.c.state = s
|
i.c.state = s
|
||||||
|
return nil
|
||||||
case *createdState:
|
case *createdState:
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -158,6 +160,7 @@ func (i *createdState) transition(s containerState) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (i *createdState) destroy() error {
|
func (i *createdState) destroy() error {
|
||||||
|
i.c.initProcess.signal(syscall.SIGKILL)
|
||||||
return destroy(i.c)
|
return destroy(i.c)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -6,10 +6,11 @@ import "testing"
|
||||||
|
|
||||||
func TestStateStatus(t *testing.T) {
|
func TestStateStatus(t *testing.T) {
|
||||||
states := map[containerState]Status{
|
states := map[containerState]Status{
|
||||||
&stoppedState{}: Destroyed,
|
&stoppedState{}: Stopped,
|
||||||
&runningState{}: Running,
|
&runningState{}: Running,
|
||||||
&restoredState{}: Running,
|
&restoredState{}: Running,
|
||||||
&pausedState{}: Paused,
|
&pausedState{}: Paused,
|
||||||
|
&createdState{}: Created,
|
||||||
}
|
}
|
||||||
for s, status := range states {
|
for s, status := range states {
|
||||||
if s.status() != status {
|
if s.status() != status {
|
||||||
|
|
4
start.go
4
start.go
|
@ -1,8 +1,6 @@
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"syscall"
|
|
||||||
|
|
||||||
"github.com/codegangsta/cli"
|
"github.com/codegangsta/cli"
|
||||||
"github.com/opencontainers/runc/libcontainer"
|
"github.com/opencontainers/runc/libcontainer"
|
||||||
)
|
)
|
||||||
|
@ -26,7 +24,7 @@ your host.`,
|
||||||
fatal(err)
|
fatal(err)
|
||||||
}
|
}
|
||||||
if status == libcontainer.Created {
|
if status == libcontainer.Created {
|
||||||
if err := container.Signal(syscall.SIGCONT); err != nil {
|
if err := container.Signal(libcontainer.InitContinueSignal); err != nil {
|
||||||
fatal(err)
|
fatal(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,7 +23,7 @@ function teardown() {
|
||||||
|
|
||||||
runc kill test_busybox KILL
|
runc kill test_busybox KILL
|
||||||
# wait for busybox to be in the destroyed state
|
# wait for busybox to be in the destroyed state
|
||||||
retry 10 1 eval "__runc state test_busybox | grep -q 'destroyed'"
|
retry 10 1 eval "__runc state test_busybox | grep -q 'stopped'"
|
||||||
|
|
||||||
# delete test_busybox
|
# delete test_busybox
|
||||||
runc delete test_busybox
|
runc delete test_busybox
|
||||||
|
|
|
@ -12,8 +12,8 @@ function teardown() {
|
||||||
}
|
}
|
||||||
|
|
||||||
@test "runc exec" {
|
@test "runc exec" {
|
||||||
# start busybox detached
|
# run busybox detached
|
||||||
runc start -d --console /dev/pts/ptmx test_busybox
|
runc run -d --console /dev/pts/ptmx test_busybox
|
||||||
[ "$status" -eq 0 ]
|
[ "$status" -eq 0 ]
|
||||||
|
|
||||||
wait_for_container 15 1 test_busybox
|
wait_for_container 15 1 test_busybox
|
||||||
|
@ -25,8 +25,8 @@ function teardown() {
|
||||||
}
|
}
|
||||||
|
|
||||||
@test "runc exec --pid-file" {
|
@test "runc exec --pid-file" {
|
||||||
# start busybox detached
|
# run busybox detached
|
||||||
runc start -d --console /dev/pts/ptmx test_busybox
|
runc run -d --console /dev/pts/ptmx test_busybox
|
||||||
[ "$status" -eq 0 ]
|
[ "$status" -eq 0 ]
|
||||||
|
|
||||||
wait_for_container 15 1 test_busybox
|
wait_for_container 15 1 test_busybox
|
||||||
|
|
|
@ -153,7 +153,7 @@ function teardown_running_container() {
|
||||||
runc list
|
runc list
|
||||||
if [[ "${output}" == *"$1"* ]]; then
|
if [[ "${output}" == *"$1"* ]]; then
|
||||||
runc kill $1 KILL
|
runc kill $1 KILL
|
||||||
retry 10 1 eval "__runc state '$1' | grep -q 'destroyed'"
|
retry 10 1 eval "__runc state '$1' | grep -q 'stopped'"
|
||||||
runc delete $1
|
runc delete $1
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
@ -162,7 +162,7 @@ function teardown_running_container_inroot() {
|
||||||
ROOT=$2 runc list
|
ROOT=$2 runc list
|
||||||
if [[ "${output}" == *"$1"* ]]; then
|
if [[ "${output}" == *"$1"* ]]; then
|
||||||
ROOT=$2 runc kill $1 KILL
|
ROOT=$2 runc kill $1 KILL
|
||||||
retry 10 1 eval "ROOT='$2' __runc state '$1' | grep -q 'destroyed'"
|
retry 10 1 eval "ROOT='$2' __runc state '$1' | grep -q 'stopped'"
|
||||||
ROOT=$2 runc delete $1
|
ROOT=$2 runc delete $1
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,7 +26,7 @@ function teardown() {
|
||||||
runc kill test_busybox KILL
|
runc kill test_busybox KILL
|
||||||
[ "$status" -eq 0 ]
|
[ "$status" -eq 0 ]
|
||||||
|
|
||||||
retry 10 1 eval "__runc state test_busybox | grep -q 'destroyed'"
|
retry 10 1 eval "__runc state test_busybox | grep -q 'stopped'"
|
||||||
|
|
||||||
runc delete test_busybox
|
runc delete test_busybox
|
||||||
[ "$status" -eq 0 ]
|
[ "$status" -eq 0 ]
|
||||||
|
|
|
@ -42,13 +42,13 @@ function teardown() {
|
||||||
|
|
||||||
runc kill test_busybox KILL
|
runc kill test_busybox KILL
|
||||||
[ "$status" -eq 0 ]
|
[ "$status" -eq 0 ]
|
||||||
retry 10 1 eval "__runc state test_busybox | grep -q 'destroyed'"
|
retry 10 1 eval "__runc state test_busybox | grep -q 'stopped'"
|
||||||
runc delete test_busybox
|
runc delete test_busybox
|
||||||
[ "$status" -eq 0 ]
|
[ "$status" -eq 0 ]
|
||||||
|
|
||||||
ROOT=$HELLO_BUNDLE runc kill test_dotbox KILL
|
ROOT=$HELLO_BUNDLE runc kill test_dotbox KILL
|
||||||
[ "$status" -eq 0 ]
|
[ "$status" -eq 0 ]
|
||||||
retry 10 1 eval "ROOT='$HELLO_BUNDLE' __runc state test_dotbox | grep -q 'destroyed'"
|
retry 10 1 eval "ROOT='$HELLO_BUNDLE' __runc state test_dotbox | grep -q 'stopped'"
|
||||||
ROOT=$HELLO_BUNDLE runc delete test_dotbox
|
ROOT=$HELLO_BUNDLE runc delete test_dotbox
|
||||||
[ "$status" -eq 0 ]
|
[ "$status" -eq 0 ]
|
||||||
}
|
}
|
||||||
|
|
|
@ -40,7 +40,7 @@ function teardown() {
|
||||||
|
|
||||||
runc kill test_busybox KILL
|
runc kill test_busybox KILL
|
||||||
# wait for busybox to be in the destroyed state
|
# wait for busybox to be in the destroyed state
|
||||||
retry 10 1 eval "__runc state test_busybox | grep -q 'destroyed'"
|
retry 10 1 eval "__runc state test_busybox | grep -q 'stopped'"
|
||||||
|
|
||||||
# delete test_busybox
|
# delete test_busybox
|
||||||
runc delete test_busybox
|
runc delete test_busybox
|
||||||
|
|
|
@ -247,7 +247,7 @@ func (r *runner) run(config *specs.Process) (int, error) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if !r.create {
|
if !r.create {
|
||||||
if err := process.Signal(syscall.SIGCONT); err != nil {
|
if err := process.Signal(libcontainer.InitContinueSignal); err != nil {
|
||||||
r.terminate(process)
|
r.terminate(process)
|
||||||
r.destroy()
|
r.destroy()
|
||||||
tty.Close()
|
tty.Close()
|
||||||
|
|
Loading…
Reference in New Issue