summaryrefslogtreecommitdiffhomepage
path: root/runsc
diff options
context:
space:
mode:
authorAndrei Vagin <avagin@google.com>2019-01-29 17:14:26 -0800
committerShentubot <shentubot@google.com>2019-01-29 17:15:56 -0800
commitdd577f5410a90d31a927b7b0fd6c4bb32b34b9f9 (patch)
treebdf421c5737f428c40bba5ee7aecbce7b6173d3a /runsc
parentff1c3bb0b577a4ea55a64de39415a8d31142b741 (diff)
runsc: reap a sandbox process only in sandbox.Wait()
PiperOrigin-RevId: 231504064 Change-Id: I585b769aef04a3ad7e7936027958910a6eed9c8d
Diffstat (limited to 'runsc')
-rw-r--r--runsc/boot/controller.go2
-rw-r--r--runsc/sandbox/sandbox.go31
2 files changed, 20 insertions, 13 deletions
diff --git a/runsc/boot/controller.go b/runsc/boot/controller.go
index 989f49388..23d476f7f 100644
--- a/runsc/boot/controller.go
+++ b/runsc/boot/controller.go
@@ -235,7 +235,7 @@ func (cm *containerManager) Start(args *StartArgs, _ *struct{}) error {
err := cm.l.startContainer(cm.l.k, args.Spec, args.Conf, args.CID, args.FilePayload.Files)
if err != nil {
- log.Debugf("containerManager.Start failed %q: %+v", args.CID, args)
+ log.Debugf("containerManager.Start failed %q: %+v: %v", args.CID, args, err)
return err
}
log.Debugf("Container %q started", args.CID)
diff --git a/runsc/sandbox/sandbox.go b/runsc/sandbox/sandbox.go
index 721a49141..ce8c21681 100644
--- a/runsc/sandbox/sandbox.go
+++ b/runsc/sandbox/sandbox.go
@@ -21,6 +21,7 @@ import (
"os"
"os/exec"
"strconv"
+ "sync"
"syscall"
"time"
@@ -64,6 +65,12 @@ type Sandbox struct {
// This field isn't saved to json, because only a creator of sandbox
// will have it as a child process.
child bool
+
+ // status is an exit status of a sandbox process.
+ status syscall.WaitStatus
+
+ // statusMu protects status.
+ statusMu sync.Mutex
}
// New creates the sandbox process. The caller must call Destroy() on the
@@ -628,18 +635,13 @@ func (s *Sandbox) Wait(cid string) (syscall.WaitStatus, error) {
// Wait RPC. The best we can do is ask Linux what the sandbox exit
// status was, since in most cases that will be the same as the
// container exit status.
- p, err := os.FindProcess(s.Pid)
- if err != nil {
- // "On Unix systems, FindProcess always succeeds and returns a
- // Process for the given pid, regardless of whether the process
- // exists."
- return ws, fmt.Errorf("Find process %d: %v", s.Pid, err)
+ if err := s.waitForStopped(); err != nil {
+ return ws, err
}
- ps, err := p.Wait()
- if err != nil {
- return ws, fmt.Errorf("sandbox no longer running, tried to get exit status, but Wait failed: %v", err)
+ if !s.child {
+ return ws, fmt.Errorf("sandbox no longer running and its exit status is unavailable")
}
- return ps.Sys().(syscall.WaitStatus), nil
+ return s.status, nil
}
// WaitPID waits for process 'pid' in the container's sandbox and returns its
@@ -853,10 +855,15 @@ func (s *Sandbox) waitForStopped() error {
defer cancel()
b := backoff.WithContext(backoff.NewConstantBackOff(100*time.Millisecond), ctx)
op := func() error {
- if s.child && s.Pid != 0 {
+ if s.child {
+ s.statusMu.Lock()
+ defer s.statusMu.Unlock()
+ if s.Pid == 0 {
+ return nil
+ }
// The sandbox process is a child of the current process,
// so we can wait it and collect its zombie.
- wpid, err := syscall.Wait4(int(s.Pid), nil, syscall.WNOHANG, nil)
+ wpid, err := syscall.Wait4(int(s.Pid), &s.status, syscall.WNOHANG, nil)
if err != nil {
return fmt.Errorf("error waiting the sandbox process: %v", err)
}