diff options
author | Andrei Vagin <avagin@google.com> | 2019-01-29 17:14:26 -0800 |
---|---|---|
committer | Shentubot <shentubot@google.com> | 2019-01-29 17:15:56 -0800 |
commit | dd577f5410a90d31a927b7b0fd6c4bb32b34b9f9 (patch) | |
tree | bdf421c5737f428c40bba5ee7aecbce7b6173d3a | |
parent | ff1c3bb0b577a4ea55a64de39415a8d31142b741 (diff) |
runsc: reap a sandbox process only in sandbox.Wait()
PiperOrigin-RevId: 231504064
Change-Id: I585b769aef04a3ad7e7936027958910a6eed9c8d
-rw-r--r-- | runsc/boot/controller.go | 2 | ||||
-rw-r--r-- | runsc/sandbox/sandbox.go | 31 |
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) } |