summaryrefslogtreecommitdiffhomepage
path: root/runsc/container
diff options
context:
space:
mode:
authorKevin Krakauer <krakauer@google.com>2018-06-28 14:55:46 -0700
committerShentubot <shentubot@google.com>2018-06-28 14:56:36 -0700
commit16d37973ebc8f36ef613c0885879648cceaf1c45 (patch)
treec797f2c9352518b5372e961b74a6ae14f56fc307 /runsc/container
parent5a8e014c3d424abfe931b8493d06a129c3fdd388 (diff)
runsc: Add the "wait" subcommand.
Users can now call "runsc wait <container id>" 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
Diffstat (limited to 'runsc/container')
-rw-r--r--runsc/container/container.go14
-rw-r--r--runsc/container/container_test.go49
2 files changed, 50 insertions, 13 deletions
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()
}