From 16d37973ebc8f36ef613c0885879648cceaf1c45 Mon Sep 17 00:00:00 2001 From: Kevin Krakauer Date: Thu, 28 Jun 2018 14:55:46 -0700 Subject: runsc: Add the "wait" subcommand. Users can now call "runsc wait " to wait on a particular process inside the container. -pid can also be used to wait on a specific PID. Manually tested the wait subcommand for a single waiter and multiple waiters (simultaneously 2 processes waiting on the container and 2 processes waiting on a PID within the container). PiperOrigin-RevId: 202548978 Change-Id: Idd507c2cdea613c3a14879b51cfb0f7ea3fb3d4c --- runsc/container/container.go | 14 +++++++++++ runsc/container/container_test.go | 49 ++++++++++++++++++++++++++++----------- 2 files changed, 50 insertions(+), 13 deletions(-) (limited to 'runsc/container') diff --git a/runsc/container/container.go b/runsc/container/container.go index b2ea78084..042c76577 100644 --- a/runsc/container/container.go +++ b/runsc/container/container.go @@ -353,6 +353,20 @@ func (c *Container) Wait() (syscall.WaitStatus, error) { return c.Sandbox.Wait(c.ID) } +// WaitRootPID waits for process 'pid' in the sandbox's PID namespace and +// returns its WaitStatus. +func (c *Container) WaitRootPID(pid int32) (syscall.WaitStatus, error) { + log.Debugf("Wait on pid %d in sandbox %q", pid, c.Sandbox.ID) + return c.Sandbox.WaitPID(pid, c.Sandbox.ID) +} + +// WaitPID waits for process 'pid' in the container's PID namespace and returns +// its WaitStatus. +func (c *Container) WaitPID(pid int32) (syscall.WaitStatus, error) { + log.Debugf("Wait on pid %d in container %q", pid, c.ID) + return c.Sandbox.WaitPID(pid, c.ID) +} + // Signal sends the signal to the container. func (c *Container) Signal(sig syscall.Signal) error { log.Debugf("Signal container %q", c.ID) diff --git a/runsc/container/container_test.go b/runsc/container/container_test.go index 11285a123..ae500e7d0 100644 --- a/runsc/container/container_test.go +++ b/runsc/container/container_test.go @@ -75,9 +75,9 @@ func procListsEqual(got, want []*control.Process) bool { pd1 := got[i] pd2 := want[i] // Zero out unimplemented and timing dependant fields. - pd1.Time, pd2.Time = "", "" - pd1.STime, pd2.STime = "", "" - pd1.C, pd2.C = 0, 0 + pd1.Time = "" + pd1.STime = "" + pd1.C = 0 if *pd1 != *pd2 { return false } @@ -1074,16 +1074,39 @@ func TestMultiContainerWait(t *testing.T) { t.Errorf("failed to wait for sleep to start: %v", err) } - // Wait on the short lived container. - if ws, err := containers[1].Wait(); err != nil { - t.Fatalf("failed to wait for process %q: %v", strings.Join(containers[1].Spec.Process.Args, " "), err) - } else if es := ws.ExitStatus(); es != 0 { - t.Fatalf("process %q exited with non-zero status %d", strings.Join(containers[1].Spec.Process.Args, " "), es) - } + // Wait on the short lived container from multiple goroutines. + wg := sync.WaitGroup{} + for i := 0; i < 3; i++ { + wg.Add(1) + go func() { + defer wg.Done() + if ws, err := containers[1].Wait(); err != nil { + t.Errorf("failed to wait for process %q: %v", strings.Join(containers[1].Spec.Process.Args, " "), err) + } else if es := ws.ExitStatus(); es != 0 { + t.Errorf("process %q exited with non-zero status %d", strings.Join(containers[1].Spec.Process.Args, " "), es) + } - // After Wait returns, ensure that the root container is running and - // the child has finished. - if err := waitForProcessList(containers[0], expectedPL[:1]); err != nil { - t.Errorf("failed to wait for %q to start: %v", strings.Join(containers[0].Spec.Process.Args, " "), err) + // After Wait returns, ensure that the root container is running and + // the child has finished. + if err := waitForProcessList(containers[0], expectedPL[:1]); err != nil { + t.Errorf("failed to wait for %q to start: %v", strings.Join(containers[0].Spec.Process.Args, " "), err) + } + }() + } + + // Also wait via PID. + for i := 0; i < 3; i++ { + wg.Add(1) + go func() { + defer wg.Done() + const pid = 2 + if ws, err := containers[0].WaitPID(pid); err != nil { + t.Errorf("failed to wait for PID %d: %v", pid, err) + } else if es := ws.ExitStatus(); es != 0 { + t.Errorf("PID %d exited with non-zero status %d", pid, es) + } + }() } + + wg.Wait() } -- cgit v1.2.3