Fix signal handling for unit tests

Signed-off-by: Michael Crosby <crosbymichael@gmail.com>
This commit is contained in:
Michael Crosby 2016-05-19 17:28:58 -07:00
parent 60f5df6e09
commit efcd73fb5b
22 changed files with 125 additions and 88 deletions

View File

@ -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

View File

@ -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.

View File

@ -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,15 +397,16 @@ 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 {
return err
}
return c.state.transition(&pausedState{
c: c,
})
} }
if err := c.cgroupManager.Freeze(configs.Frozen); err != nil { return newGenericError(fmt.Errorf("container not running: %s", status), ContainerNotRunning)
return err
}
return c.state.transition(&pausedState{
c: c,
})
} }
func (c *linuxContainer) Resume() error { func (c *linuxContainer) Resume() error {

View File

@ -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 {

View File

@ -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 {

View File

@ -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)

View File

@ -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()

View File

@ -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)
} }

View File

@ -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", {
Destination: "/dev/mqueue", Source: "mqueue",
Device: "mqueue", Destination: "/dev/mqueue",
Flags: defaultMountFlags, Device: "mqueue",
}, Flags: defaultMountFlags,
},
*/
{ {
Source: "sysfs", Source: "sysfs",
Destination: "/sys", Destination: "/sys",

View File

@ -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

View File

@ -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
} }

View File

@ -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)
} }

View File

@ -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 {

2
run.go
View File

@ -40,7 +40,7 @@ command(s) that get executed on start, edit the args parameter of the spec. See
Usage: "specify the pty slave path for use with the container", Usage: "specify the pty slave path for use with the container",
}, },
cli.BoolFlag{ cli.BoolFlag{
Name: "detach,d", Name: "detach, d",
Usage: "detach from the container's process", Usage: "detach from the container's process",
}, },
cli.StringFlag{ cli.StringFlag{

View File

@ -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)
} }
} }

View File

@ -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

View File

@ -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

View File

@ -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
} }

View File

@ -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 ]

View File

@ -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 ]
} }

View File

@ -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

View File

@ -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()