diff options
Diffstat (limited to 'runsc/container')
-rw-r--r-- | runsc/container/console_test.go | 24 | ||||
-rw-r--r-- | runsc/container/container.go | 27 | ||||
-rw-r--r-- | runsc/container/container_norace_test.go | 1 | ||||
-rw-r--r-- | runsc/container/container_race_test.go | 1 | ||||
-rw-r--r-- | runsc/container/container_test.go | 55 | ||||
-rw-r--r-- | runsc/container/hook.go | 4 | ||||
-rw-r--r-- | runsc/container/multi_container_test.go | 53 | ||||
-rw-r--r-- | runsc/container/shared_volume_test.go | 30 | ||||
-rw-r--r-- | runsc/container/state_file.go | 15 |
9 files changed, 122 insertions, 88 deletions
diff --git a/runsc/container/console_test.go b/runsc/container/console_test.go index 79b056fce..9d36086c3 100644 --- a/runsc/container/console_test.go +++ b/runsc/container/console_test.go @@ -288,7 +288,7 @@ func TestJobControlSignalExec(t *testing.T) { StdioIsPty: true, } - pid, err := c.Execute(execArgs) + pid, err := c.Execute(conf, execArgs) if err != nil { t.Fatalf("error executing: %v", err) } @@ -308,7 +308,9 @@ func TestJobControlSignalExec(t *testing.T) { } // Execute sleep. - ptyMaster.Write([]byte("sleep 100\n")) + if _, err := ptyMaster.Write([]byte("sleep 100\n")); err != nil { + t.Fatalf("ptyMaster.Write: %v", err) + } // Wait for it to start. Sleep's PPID is bash's PID. expectedPL = append(expectedPL, newProcessBuilder().PID(3).PPID(2).Cmd("sleep").Process()) @@ -411,7 +413,9 @@ func TestJobControlSignalRootContainer(t *testing.T) { // which makes this a suitable Reader for WaitUntilRead. ptyBuf := newBlockingBuffer() tee := io.TeeReader(ptyMaster, ptyBuf) - go io.Copy(os.Stderr, tee) + go func() { + _, _ = io.Copy(os.Stderr, tee) + }() // Start the container. if err := c.Start(conf); err != nil { @@ -444,7 +448,9 @@ func TestJobControlSignalRootContainer(t *testing.T) { } // Execute sleep via the terminal. - ptyMaster.Write([]byte("sleep 100\n")) + if _, err := ptyMaster.Write([]byte("sleep 100\n")); err != nil { + t.Fatalf("ptyMaster.Write(): %v", err) + } // Wait for sleep to start. expectedPL = append(expectedPL, newProcessBuilder().PID(2).PPID(1).Cmd("sleep").Process()) @@ -563,13 +569,15 @@ func TestMultiContainerTerminal(t *testing.T) { // file. Writes after a certain point will block unless we drain the // PTY, so we must continually copy from it. // - // We log the output to stderr for debugabilitly, and also to a buffer, + // We log the output to stderr for debuggability, and also to a buffer, // since we wait on particular output from bash below. We use a custom // blockingBuffer which is thread-safe and also blocks on Read calls, // which makes this a suitable Reader for WaitUntilRead. ptyBuf := newBlockingBuffer() tee := io.TeeReader(tc.master, ptyBuf) - go io.Copy(os.Stderr, tee) + go func() { + _, _ = io.Copy(os.Stderr, tee) + }() // Wait for bash to start. expectedPL := []*control.Process{ @@ -581,7 +589,9 @@ func TestMultiContainerTerminal(t *testing.T) { // Execute echo command and check that it was executed correctly. Use // a variable to ensure it's not matching against command echo. - tc.master.Write([]byte("echo foo-${PWD}-123\n")) + if _, err := tc.master.Write([]byte("echo foo-${PWD}-123\n")); err != nil { + t.Fatalf("master.Write(): %v", err) + } if err := testutil.WaitUntilRead(ptyBuf, "foo-/-123", 5*time.Second); err != nil { t.Fatalf("echo didn't execute: %v", err) } diff --git a/runsc/container/container.go b/runsc/container/container.go index 0820edaec..7f066905a 100644 --- a/runsc/container/container.go +++ b/runsc/container/container.go @@ -208,7 +208,7 @@ func New(conf *config.Config, args Args) (*Container, error) { if err := c.Saver.lockForNew(); err != nil { return nil, err } - defer c.Saver.unlock() + defer c.Saver.unlockOrDie() // If the metadata annotations indicate that this container should be started // in an existing sandbox, we must do so. These are the possible metadata @@ -310,7 +310,7 @@ func New(conf *config.Config, args Args) (*Container, error) { defer tty.Close() } - if err := c.Sandbox.CreateContainer(c.ID, tty); err != nil { + if err := c.Sandbox.CreateSubcontainer(conf, c.ID, tty); err != nil { return nil, err } } @@ -340,7 +340,7 @@ func (c *Container) Start(conf *config.Config) error { if err := c.Saver.lock(); err != nil { return err } - unlock := cleanup.Make(func() { c.Saver.unlock() }) + unlock := cleanup.Make(c.Saver.unlockOrDie) defer unlock.Clean() if err := c.requireStatus("start", Created); err != nil { @@ -388,7 +388,7 @@ func (c *Container) Start(conf *config.Config) error { stdios = []*os.File{os.Stdin, os.Stdout, os.Stderr} } - return c.Sandbox.StartContainer(c.Spec, conf, c.ID, stdios, goferFiles) + return c.Sandbox.StartSubcontainer(c.Spec, conf, c.ID, stdios, goferFiles) }); err != nil { return err } @@ -426,7 +426,7 @@ func (c *Container) Restore(spec *specs.Spec, conf *config.Config, restoreFile s if err := c.Saver.lock(); err != nil { return err } - defer c.Saver.unlock() + defer c.Saver.unlockOrDie() if err := c.requireStatus("restore", Created); err != nil { return err @@ -480,13 +480,13 @@ func Run(conf *config.Config, args Args) (unix.WaitStatus, error) { // Execute runs the specified command in the container. It returns the PID of // the newly created process. -func (c *Container) Execute(args *control.ExecArgs) (int32, error) { +func (c *Container) Execute(conf *config.Config, args *control.ExecArgs) (int32, error) { log.Debugf("Execute in container, cid: %s, args: %+v", c.ID, args) if err := c.requireStatus("execute in", Created, Running); err != nil { return 0, err } args.ContainerID = c.ID - return c.Sandbox.Execute(args) + return c.Sandbox.Execute(conf, args) } // Event returns events for the container. @@ -614,7 +614,7 @@ func (c *Container) Pause() error { if err := c.Saver.lock(); err != nil { return err } - defer c.Saver.unlock() + defer c.Saver.unlockOrDie() if c.Status != Created && c.Status != Running { return fmt.Errorf("cannot pause container %q in state %v", c.ID, c.Status) @@ -634,7 +634,7 @@ func (c *Container) Resume() error { if err := c.Saver.lock(); err != nil { return err } - defer c.Saver.unlock() + defer c.Saver.unlockOrDie() if c.Status != Paused { return fmt.Errorf("cannot resume container %q in state %v", c.ID, c.Status) @@ -675,8 +675,8 @@ func (c *Container) Destroy() error { return err } defer func() { - c.Saver.unlock() - c.Saver.close() + c.Saver.unlockOrDie() + _ = c.Saver.close() }() // Stored for later use as stop() sets c.Sandbox to nil. @@ -910,6 +910,9 @@ func (c *Container) createGoferProcess(spec *specs.Spec, conf *config.Config, bu binPath := specutils.ExePath cmd := exec.Command(binPath, args...) cmd.ExtraFiles = goferEnds + + // Set Args[0] to make easier to spot the gofer process. Otherwise it's + // shown as `exe`. cmd.Args[0] = "runsc-gofer" if attached { @@ -1020,10 +1023,10 @@ func runInCgroup(cg *cgroup.Cgroup, fn func() error) error { return fn() } restore, err := cg.Join() - defer restore() if err != nil { return err } + defer restore() return fn() } diff --git a/runsc/container/container_norace_test.go b/runsc/container/container_norace_test.go index 838c1e20a..a4daf16ed 100644 --- a/runsc/container/container_norace_test.go +++ b/runsc/container/container_norace_test.go @@ -12,6 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. +//go:build !race // +build !race package container diff --git a/runsc/container/container_race_test.go b/runsc/container/container_race_test.go index 9fb4c4fc0..86a57145c 100644 --- a/runsc/container/container_race_test.go +++ b/runsc/container/container_race_test.go @@ -12,6 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. +//go:build race // +build race package container diff --git a/runsc/container/container_test.go b/runsc/container/container_test.go index 249324c5a..5fb4a3672 100644 --- a/runsc/container/container_test.go +++ b/runsc/container/container_test.go @@ -53,19 +53,22 @@ func TestMain(m *testing.M) { if err := testutil.ConfigureExePath(); err != nil { panic(err.Error()) } - specutils.MaybeRunAsRoot() + if err := specutils.MaybeRunAsRoot(); err != nil { + fmt.Fprintf(os.Stderr, "Error running as root: %v", err) + os.Exit(123) + } os.Exit(m.Run()) } -func execute(cont *Container, name string, arg ...string) (unix.WaitStatus, error) { +func execute(conf *config.Config, cont *Container, name string, arg ...string) (unix.WaitStatus, error) { args := &control.ExecArgs{ Filename: name, Argv: append([]string{name}, arg...), } - return cont.executeSync(args) + return cont.executeSync(conf, args) } -func executeCombinedOutput(cont *Container, name string, arg ...string) ([]byte, error) { +func executeCombinedOutput(conf *config.Config, cont *Container, name string, arg ...string) ([]byte, error) { r, w, err := os.Pipe() if err != nil { return nil, err @@ -77,7 +80,7 @@ func executeCombinedOutput(cont *Container, name string, arg ...string) ([]byte, Argv: append([]string{name}, arg...), FilePayload: urpc.FilePayload{Files: []*os.File{os.Stdin, w, w}}, } - ws, err := cont.executeSync(args) + ws, err := cont.executeSync(conf, args) w.Close() if err != nil { return nil, err @@ -91,8 +94,8 @@ func executeCombinedOutput(cont *Container, name string, arg ...string) ([]byte, } // executeSync synchronously executes a new process. -func (c *Container) executeSync(args *control.ExecArgs) (unix.WaitStatus, error) { - pid, err := c.Execute(args) +func (c *Container) executeSync(conf *config.Config, args *control.ExecArgs) (unix.WaitStatus, error) { + pid, err := c.Execute(conf, args) if err != nil { return 0, fmt.Errorf("error executing: %v", err) } @@ -169,8 +172,8 @@ func blockUntilWaitable(pid int) error { } // execPS executes `ps` inside the container and return the processes. -func execPS(c *Container) ([]*control.Process, error) { - out, err := executeCombinedOutput(c, "/bin/ps", "-e") +func execPS(conf *config.Config, c *Container) ([]*control.Process, error) { + out, err := executeCombinedOutput(conf, c, "/bin/ps", "-e") if err != nil { return nil, err } @@ -523,9 +526,11 @@ func TestLifecycle(t *testing.T) { ws, err := c.Wait() if err != nil { ch <- err + return } if got, want := ws.Signal(), unix.SIGTERM; got != want { ch <- fmt.Errorf("got signal %v, want %v", got, want) + return } ch <- nil }() @@ -859,7 +864,7 @@ func TestExec(t *testing.T) { } { t.Run(tc.name, func(t *testing.T) { // t.Parallel() - if ws, err := cont.executeSync(&tc.args); err != nil { + if ws, err := cont.executeSync(conf, &tc.args); err != nil { t.Fatalf("executeAsync(%+v): %v", tc.args, err) } else if ws != 0 { t.Fatalf("executeAsync(%+v) failed with exit: %v", tc.args, ws) @@ -877,7 +882,7 @@ func TestExec(t *testing.T) { } defer unix.Close(fds[0]) - _, err = cont.executeSync(&control.ExecArgs{ + _, err = cont.executeSync(conf, &control.ExecArgs{ Argv: []string{"/nonexist"}, FilePayload: urpc.FilePayload{ Files: []*os.File{os.NewFile(uintptr(fds[1]), "sock")}, @@ -932,7 +937,7 @@ func TestExecProcList(t *testing.T) { // start running exec (which blocks). ch := make(chan error) go func() { - exitStatus, err := cont.executeSync(execArgs) + exitStatus, err := cont.executeSync(conf, execArgs) if err != nil { ch <- err } else if exitStatus != 0 { @@ -1525,7 +1530,9 @@ func TestCapabilities(t *testing.T) { defer os.Remove(exePath) // Need to traverse the intermediate directory. - os.Chmod(rootDir, 0755) + if err := os.Chmod(rootDir, 0755); err != nil { + t.Fatal(err) + } execArgs := &control.ExecArgs{ Filename: exePath, @@ -1537,7 +1544,7 @@ func TestCapabilities(t *testing.T) { } // "exe" should fail because we don't have the necessary permissions. - if _, err := cont.executeSync(execArgs); err == nil { + if _, err := cont.executeSync(conf, execArgs); err == nil { t.Fatalf("container executed without error, but an error was expected") } @@ -1546,7 +1553,7 @@ func TestCapabilities(t *testing.T) { EffectiveCaps: auth.CapabilitySetOf(linux.CAP_DAC_OVERRIDE), } // "exe" should not fail this time. - if _, err := cont.executeSync(execArgs); err != nil { + if _, err := cont.executeSync(conf, execArgs); err != nil { t.Fatalf("container failed to exec %v: %v", args, err) } }) @@ -1657,7 +1664,7 @@ func TestReadonlyRoot(t *testing.T) { } // Read mounts to check that root is readonly. - out, err := executeCombinedOutput(c, "/bin/sh", "-c", "mount | grep ' / ' | grep -o -e '(.*)'") + out, err := executeCombinedOutput(conf, c, "/bin/sh", "-c", "mount | grep ' / ' | grep -o -e '(.*)'") if err != nil { t.Fatalf("exec failed: %v", err) } @@ -1667,7 +1674,7 @@ func TestReadonlyRoot(t *testing.T) { } // Check that file cannot be created. - ws, err := execute(c, "/bin/touch", "/foo") + ws, err := execute(conf, c, "/bin/touch", "/foo") if err != nil { t.Fatalf("touch file in ro mount: %v", err) } @@ -1716,7 +1723,7 @@ func TestReadonlyMount(t *testing.T) { // Read mounts to check that volume is readonly. cmd := fmt.Sprintf("mount | grep ' %s ' | grep -o -e '(.*)'", dir) - out, err := executeCombinedOutput(c, "/bin/sh", "-c", cmd) + out, err := executeCombinedOutput(conf, c, "/bin/sh", "-c", cmd) if err != nil { t.Fatalf("exec failed, err: %v", err) } @@ -1726,7 +1733,7 @@ func TestReadonlyMount(t *testing.T) { } // Check that file cannot be created. - ws, err := execute(c, "/bin/touch", path.Join(dir, "file")) + ws, err := execute(conf, c, "/bin/touch", path.Join(dir, "file")) if err != nil { t.Fatalf("touch file in ro mount: %v", err) } @@ -2153,7 +2160,7 @@ func doDestroyStartingTest(t *testing.T, vfs2 bool) { go func() { defer wg.Done() // Ignore failures, start can fail if destroy runs first. - startCont.Start(conf) + _ = startCont.Start(conf) }() wg.Add(1) @@ -2271,13 +2278,13 @@ func TestMountPropagation(t *testing.T) { // Check that mount didn't propagate to private mount. privFile := filepath.Join(priv, "mnt", "file") - if ws, err := execute(cont, "/usr/bin/test", "!", "-f", privFile); err != nil || ws != 0 { + if ws, err := execute(conf, cont, "/usr/bin/test", "!", "-f", privFile); err != nil || ws != 0 { t.Fatalf("exec: test ! -f %q, ws: %v, err: %v", privFile, ws, err) } // Check that mount propagated to slave mount. slaveFile := filepath.Join(slave, "mnt", "file") - if ws, err := execute(cont, "/usr/bin/test", "-f", slaveFile); err != nil || ws != 0 { + if ws, err := execute(conf, cont, "/usr/bin/test", "-f", slaveFile); err != nil || ws != 0 { t.Fatalf("exec: test -f %q, ws: %v, err: %v", privFile, ws, err) } } @@ -2343,7 +2350,7 @@ func TestMountSymlink(t *testing.T) { // Check that symlink was resolved and mount was created where the symlink // is pointing to. file := path.Join(target, "file") - if ws, err := execute(cont, "/usr/bin/test", "-f", file); err != nil || ws != 0 { + if ws, err := execute(conf, cont, "/usr/bin/test", "-f", file); err != nil || ws != 0 { t.Fatalf("exec: test -f %q, ws: %v, err: %v", file, ws, err) } }) @@ -2582,7 +2589,7 @@ func TestRlimitsExec(t *testing.T) { t.Fatalf("error starting container: %v", err) } - got, err := executeCombinedOutput(cont, "/bin/sh", "-c", "ulimit -n") + got, err := executeCombinedOutput(conf, cont, "/bin/sh", "-c", "ulimit -n") if err != nil { t.Fatal(err) } diff --git a/runsc/container/hook.go b/runsc/container/hook.go index 901607aee..ce1c9e1de 100644 --- a/runsc/container/hook.go +++ b/runsc/container/hook.go @@ -101,8 +101,8 @@ func executeHook(h specs.Hook, s specs.State) error { return fmt.Errorf("failure executing hook %q, err: %v\nstdout: %s\nstderr: %s", h.Path, err, stdout.String(), stderr.String()) } case <-timer: - cmd.Process.Kill() - cmd.Wait() + _ = cmd.Process.Kill() + _ = cmd.Wait() return fmt.Errorf("timeout executing hook %q\nstdout: %s\nstderr: %s", h.Path, stdout.String(), stderr.String()) } diff --git a/runsc/container/multi_container_test.go b/runsc/container/multi_container_test.go index 0dbe1e323..9d8022e50 100644 --- a/runsc/container/multi_container_test.go +++ b/runsc/container/multi_container_test.go @@ -105,11 +105,11 @@ type execDesc struct { name string } -func execMany(t *testing.T, execs []execDesc) { +func execMany(t *testing.T, conf *config.Config, execs []execDesc) { for _, exec := range execs { t.Run(exec.name, func(t *testing.T) { args := &control.ExecArgs{Argv: exec.cmd} - if ws, err := exec.c.executeSync(args); err != nil { + if ws, err := exec.c.executeSync(conf, args); err != nil { t.Errorf("error executing %+v: %v", args, err) } else if ws.ExitStatus() != exec.want { t.Errorf("%q: exec %q got exit status: %d, want: %d", exec.name, exec.cmd, ws.ExitStatus(), exec.want) @@ -217,7 +217,7 @@ func TestMultiPIDNS(t *testing.T) { newProcessBuilder().PID(2).Cmd("sleep").Process(), newProcessBuilder().Cmd("ps").Process(), } - got, err := execPS(containers[0]) + got, err := execPS(conf, containers[0]) if err != nil { t.Fatal(err) } @@ -229,7 +229,7 @@ func TestMultiPIDNS(t *testing.T) { newProcessBuilder().PID(1).Cmd("sleep").Process(), newProcessBuilder().Cmd("ps").Process(), } - got, err = execPS(containers[1]) + got, err = execPS(conf, containers[1]) if err != nil { t.Fatal(err) } @@ -313,7 +313,7 @@ func TestMultiPIDNSPath(t *testing.T) { newProcessBuilder().PID(3).Cmd("sleep").Process(), newProcessBuilder().Cmd("ps").Process(), } - got, err := execPS(containers[0]) + got, err := execPS(conf, containers[0]) if err != nil { t.Fatal(err) } @@ -328,7 +328,7 @@ func TestMultiPIDNSPath(t *testing.T) { newProcessBuilder().PID(3).Cmd("sleep").Process(), newProcessBuilder().Cmd("ps").Process(), } - got, err = execPS(containers[1]) + got, err = execPS(conf, containers[1]) if err != nil { t.Fatal(err) } @@ -341,7 +341,7 @@ func TestMultiPIDNSPath(t *testing.T) { newProcessBuilder().PID(1).Cmd("sleep").Process(), newProcessBuilder().Cmd("ps").Process(), } - got, err = execPS(containers[2]) + got, err = execPS(conf, containers[2]) if err != nil { t.Fatal(err) } @@ -541,7 +541,7 @@ func TestExecWait(t *testing.T) { WorkingDirectory: "/", KUID: 0, } - pid, err := containers[0].Execute(args) + pid, err := containers[0].Execute(conf, args) if err != nil { t.Fatalf("error executing: %v", err) } @@ -744,7 +744,7 @@ func TestMultiContainerDestroy(t *testing.T) { Filename: app, Argv: []string{app, "fork-bomb"}, } - if _, err := containers[1].Execute(args); err != nil { + if _, err := containers[1].Execute(conf, args); err != nil { t.Fatalf("error exec'ing: %v", err) } @@ -821,7 +821,7 @@ func TestMultiContainerProcesses(t *testing.T) { Filename: "/bin/sleep", Argv: []string{"/bin/sleep", "100"}, } - if _, err := containers[1].Execute(args); err != nil { + if _, err := containers[1].Execute(conf, args); err != nil { t.Fatalf("error exec'ing: %v", err) } expectedPL1 = append(expectedPL1, newProcessBuilder().PID(4).Cmd("sleep").Process()) @@ -882,7 +882,7 @@ func TestMultiContainerKillAll(t *testing.T) { Filename: app, Argv: []string{app, "task-tree", "--depth=2", "--width=2"}, } - if _, err := containers[1].Execute(args); err != nil { + if _, err := containers[1].Execute(conf, args); err != nil { t.Fatalf("error exec'ing: %v", err) } // Wait for these new processes to start. @@ -894,7 +894,9 @@ func TestMultiContainerKillAll(t *testing.T) { if tc.killContainer { // First kill the init process to make the container be stopped with // processes still running inside. - containers[1].SignalContainer(unix.SIGKILL, false) + if err := containers[1].SignalContainer(unix.SIGKILL, false); err != nil { + t.Fatalf("SignalContainer(): %v", err) + } op := func() error { c, err := Load(conf.RootDir, FullID{ContainerID: ids[1]}, LoadOpts{}) if err != nil { @@ -912,7 +914,7 @@ func TestMultiContainerKillAll(t *testing.T) { c, err := Load(conf.RootDir, FullID{ContainerID: ids[1]}, LoadOpts{}) if err != nil { - t.Fatalf("failed to load child container %q: %v", c.ID, err) + t.Fatalf("failed to load child container %q: %v", ids[1], err) } // Kill'Em All if err := c.SignalContainer(unix.SIGKILL, true); err != nil { @@ -1040,7 +1042,8 @@ func TestMultiContainerDestroyStarting(t *testing.T) { wg.Add(1) go func() { defer wg.Done() - startCont.Start(conf) // ignore failures, start can fail if destroy runs first. + // Ignore failures, start can fail if destroy runs first. + _ = startCont.Start(conf) }() wg.Add(1) @@ -1314,7 +1317,7 @@ func TestMultiContainerSharedMount(t *testing.T) { name: "dir removed from container1", }, } - execMany(t, execs) + execMany(t, conf, execs) }) } } @@ -1379,7 +1382,7 @@ func TestMultiContainerSharedMountReadonly(t *testing.T) { name: "fails to write to container1", }, } - execMany(t, execs) + execMany(t, conf, execs) }) } } @@ -1437,7 +1440,7 @@ func TestMultiContainerSharedMountRestart(t *testing.T) { name: "file appears in container1", }, } - execMany(t, execs) + execMany(t, conf, execs) containers[1].Destroy() @@ -1487,7 +1490,7 @@ func TestMultiContainerSharedMountRestart(t *testing.T) { name: "file removed from container1", }, } - execMany(t, execs) + execMany(t, conf, execs) }) } } @@ -1540,7 +1543,7 @@ func TestMultiContainerSharedMountUnsupportedOptions(t *testing.T) { name: "directory is mounted in container1", }, } - execMany(t, execs) + execMany(t, conf, execs) }) } } @@ -1651,7 +1654,7 @@ func TestMultiContainerGoferKilled(t *testing.T) { } // Check that container isn't running anymore. - if _, err := execute(c, "/bin/true"); err == nil { + if _, err := execute(conf, c, "/bin/true"); err == nil { t.Fatalf("Container %q was not stopped after gofer death", c.ID) } @@ -1666,7 +1669,7 @@ func TestMultiContainerGoferKilled(t *testing.T) { if err := waitForProcessList(c, pl); err != nil { t.Errorf("Container %q was affected by another container: %v", c.ID, err) } - if _, err := execute(c, "/bin/true"); err != nil { + if _, err := execute(conf, c, "/bin/true"); err != nil { t.Fatalf("Container %q was affected by another container: %v", c.ID, err) } } @@ -1688,7 +1691,7 @@ func TestMultiContainerGoferKilled(t *testing.T) { // Check that entire sandbox isn't running anymore. for _, c := range containers { - if _, err := execute(c, "/bin/true"); err == nil { + if _, err := execute(conf, c, "/bin/true"); err == nil { t.Fatalf("Container %q was not stopped after gofer death", c.ID) } } @@ -1864,7 +1867,7 @@ func TestMultiContainerHomeEnvDir(t *testing.T) { defer cleanup() // Exec into the root container synchronously. - if _, err := execute(containers[0], "/bin/sh", "-c", execCmd); err != nil { + if _, err := execute(conf, containers[0], "/bin/sh", "-c", execCmd); err != nil { t.Errorf("error executing %+v: %v", execCmd, err) } @@ -1980,7 +1983,7 @@ func TestMultiContainerEvent(t *testing.T) { if busyUsage <= sleepUsage { t.Logf("Busy container usage lower than sleep (busy: %d, sleep: %d), retrying...", busyUsage, sleepUsage) - return fmt.Errorf("Busy container should have higher usage than sleep, busy: %d, sleep: %d", busyUsage, sleepUsage) + return fmt.Errorf("busy container should have higher usage than sleep, busy: %d, sleep: %d", busyUsage, sleepUsage) } return nil } @@ -2053,7 +2056,7 @@ func TestDuplicateEnvVariable(t *testing.T) { Argv: []string{"/bin/sh", "-c", cmdExec}, Envv: []string{"VAR=foo", "VAR=bar"}, } - if ws, err := containers[0].executeSync(execArgs); err != nil || ws.ExitStatus() != 0 { + if ws, err := containers[0].executeSync(conf, execArgs); err != nil || ws.ExitStatus() != 0 { t.Fatalf("exec failed, ws: %v, err: %v", ws, err) } diff --git a/runsc/container/shared_volume_test.go b/runsc/container/shared_volume_test.go index cb5bffb89..f16b2bd02 100644 --- a/runsc/container/shared_volume_test.go +++ b/runsc/container/shared_volume_test.go @@ -72,7 +72,7 @@ func TestSharedVolume(t *testing.T) { Filename: "/usr/bin/test", Argv: []string{"test", "-f", filename}, } - if ws, err := c.executeSync(argsTestFile); err != nil { + if ws, err := c.executeSync(conf, argsTestFile); err != nil { t.Fatalf("unexpected error testing file %q: %v", filename, err) } else if ws.ExitStatus() == 0 { t.Errorf("test %q exited with code %v, wanted not zero", ws.ExitStatus(), err) @@ -84,7 +84,7 @@ func TestSharedVolume(t *testing.T) { } // Now we should be able to test the file from within the sandbox. - if ws, err := c.executeSync(argsTestFile); err != nil { + if ws, err := c.executeSync(conf, argsTestFile); err != nil { t.Fatalf("unexpected error testing file %q: %v", filename, err) } else if ws.ExitStatus() != 0 { t.Errorf("test %q exited with code %v, wanted zero", filename, ws.ExitStatus()) @@ -97,7 +97,7 @@ func TestSharedVolume(t *testing.T) { } // File should no longer exist at the old path within the sandbox. - if ws, err := c.executeSync(argsTestFile); err != nil { + if ws, err := c.executeSync(conf, argsTestFile); err != nil { t.Fatalf("unexpected error testing file %q: %v", filename, err) } else if ws.ExitStatus() == 0 { t.Errorf("test %q exited with code %v, wanted not zero", filename, ws.ExitStatus()) @@ -108,7 +108,7 @@ func TestSharedVolume(t *testing.T) { Filename: "/usr/bin/test", Argv: []string{"test", "-f", newFilename}, } - if ws, err := c.executeSync(argsTestNewFile); err != nil { + if ws, err := c.executeSync(conf, argsTestNewFile); err != nil { t.Fatalf("unexpected error testing file %q: %v", newFilename, err) } else if ws.ExitStatus() != 0 { t.Errorf("test %q exited with code %v, wanted zero", newFilename, ws.ExitStatus()) @@ -120,7 +120,7 @@ func TestSharedVolume(t *testing.T) { } // Renamed file should no longer exist at the old path within the sandbox. - if ws, err := c.executeSync(argsTestNewFile); err != nil { + if ws, err := c.executeSync(conf, argsTestNewFile); err != nil { t.Fatalf("unexpected error testing file %q: %v", newFilename, err) } else if ws.ExitStatus() == 0 { t.Errorf("test %q exited with code %v, wanted not zero", newFilename, ws.ExitStatus()) @@ -133,7 +133,7 @@ func TestSharedVolume(t *testing.T) { KUID: auth.KUID(os.Getuid()), KGID: auth.KGID(os.Getgid()), } - if ws, err := c.executeSync(argsTouch); err != nil { + if ws, err := c.executeSync(conf, argsTouch); err != nil { t.Fatalf("unexpected error touching file %q: %v", filename, err) } else if ws.ExitStatus() != 0 { t.Errorf("touch %q exited with code %v, wanted zero", filename, ws.ExitStatus()) @@ -154,7 +154,7 @@ func TestSharedVolume(t *testing.T) { Filename: "/bin/rm", Argv: []string{"rm", filename}, } - if ws, err := c.executeSync(argsRemove); err != nil { + if ws, err := c.executeSync(conf, argsRemove); err != nil { t.Fatalf("unexpected error removing file %q: %v", filename, err) } else if ws.ExitStatus() != 0 { t.Errorf("remove %q exited with code %v, wanted zero", filename, ws.ExitStatus()) @@ -166,14 +166,14 @@ func TestSharedVolume(t *testing.T) { } } -func checkFile(c *Container, filename string, want []byte) error { +func checkFile(conf *config.Config, c *Container, filename string, want []byte) error { cpy := filename + ".copy" - if _, err := execute(c, "/bin/cp", "-f", filename, cpy); err != nil { + if _, err := execute(conf, c, "/bin/cp", "-f", filename, cpy); err != nil { return fmt.Errorf("unexpected error copying file %q to %q: %v", filename, cpy, err) } got, err := ioutil.ReadFile(cpy) if err != nil { - return fmt.Errorf("Error reading file %q: %v", filename, err) + return fmt.Errorf("error reading file %q: %v", filename, err) } if !bytes.Equal(got, want) { return fmt.Errorf("file content inside the sandbox is wrong, got: %q, want: %q", got, want) @@ -226,16 +226,16 @@ func TestSharedVolumeFile(t *testing.T) { if err := ioutil.WriteFile(filename, []byte(want), 0666); err != nil { t.Fatalf("Error writing to %q: %v", filename, err) } - if err := checkFile(c, filename, want); err != nil { + if err := checkFile(conf, c, filename, want); err != nil { t.Fatal(err.Error()) } // Append to file inside the container and check that content is not lost. - if _, err := execute(c, "/bin/bash", "-c", "echo -n sandbox- >> "+filename); err != nil { + if _, err := execute(conf, c, "/bin/bash", "-c", "echo -n sandbox- >> "+filename); err != nil { t.Fatalf("unexpected error appending file %q: %v", filename, err) } want = []byte("host-sandbox-") - if err := checkFile(c, filename, want); err != nil { + if err := checkFile(conf, c, filename, want); err != nil { t.Fatal(err.Error()) } @@ -250,7 +250,7 @@ func TestSharedVolumeFile(t *testing.T) { t.Fatalf("Error writing to file %q: %v", filename, err) } want = []byte("host-sandbox-host") - if err := checkFile(c, filename, want); err != nil { + if err := checkFile(conf, c, filename, want); err != nil { t.Fatal(err.Error()) } @@ -259,7 +259,7 @@ func TestSharedVolumeFile(t *testing.T) { t.Fatalf("Error truncating file %q: %v", filename, err) } want = want[:5] - if err := checkFile(c, filename, want); err != nil { + if err := checkFile(conf, c, filename, want); err != nil { t.Fatal(err.Error()) } } diff --git a/runsc/container/state_file.go b/runsc/container/state_file.go index 0399903a0..23810f593 100644 --- a/runsc/container/state_file.go +++ b/runsc/container/state_file.go @@ -264,10 +264,10 @@ func (s *StateFile) lockForNew() error { // Checks if the container already exists by looking for the metadata file. if _, err := os.Stat(s.statePath()); err == nil { - s.unlock() + s.unlockOrDie() return fmt.Errorf("container already exists") } else if !os.IsNotExist(err) { - s.unlock() + s.unlockOrDie() return fmt.Errorf("looking for existing container: %v", err) } return nil @@ -286,6 +286,15 @@ func (s *StateFile) unlock() error { return nil } +func (s *StateFile) unlockOrDie() { + if !s.flock.Locked() { + panic("unlock called without lock held") + } + if err := s.flock.Unlock(); err != nil { + panic(fmt.Sprintf("Error releasing lock on %q: %v", s.flock, err)) + } +} + // saveLocked saves 'v' to the state file. // // Preconditions: lock() must been called before. @@ -308,7 +317,7 @@ func (s *StateFile) load(v interface{}) error { if err := s.lock(); err != nil { return err } - defer s.unlock() + defer s.unlockOrDie() metaBytes, err := ioutil.ReadFile(s.statePath()) if err != nil { |