Merge pull request #282 from mlaventure/fix-race-in-process-start

Handle case where shim is reaped before the call to the runtime start
This commit is contained in:
Kenfe-Mickaël Laventure 2016-07-01 11:39:34 -07:00 committed by GitHub
commit 1b3a81545c
4 changed files with 29 additions and 18 deletions

View file

@ -258,13 +258,13 @@ func (cs *ContainerdSuite) TearDownTest(c *check.C) {
}) })
if err := cs.KillContainer(ctr.Id); err != nil { if err := cs.KillContainer(ctr.Id); err != nil {
fmt.Fprintf(os.Stderr, "Failed to cleanup leftover test containers: %v", err) fmt.Fprintf(os.Stderr, "Failed to cleanup leftover test containers: %v\n", err)
} }
select { select {
case <-ch: case <-ch:
case <-time.After(3 * time.Second): case <-time.After(3 * time.Second):
fmt.Fprintf(os.Stderr, "TearDownTest: Containerd %v didn't die after 3 seconds", ctr.Id) fmt.Fprintf(os.Stderr, "TearDownTest: Containerd %v didn't die after 3 seconds\n", ctr.Id)
} }
} }
} }

View file

@ -465,6 +465,7 @@ func (c *container) Exec(pid string, pspec specs.ProcessSpec, s Stdio) (pp Proce
func (c *container) createCmd(pid string, cmd *exec.Cmd, p *process) error { func (c *container) createCmd(pid string, cmd *exec.Cmd, p *process) error {
p.cmd = cmd p.cmd = cmd
if err := cmd.Start(); err != nil { if err := cmd.Start(); err != nil {
close(p.cmdDoneCh)
if exErr, ok := err.(*exec.Error); ok { if exErr, ok := err.(*exec.Error); ok {
if exErr.Err == exec.ErrNotFound || exErr.Err == os.ErrNotExist { if exErr.Err == exec.ErrNotFound || exErr.Err == os.ErrNotExist {
return fmt.Errorf("%s not installed on system", c.shim) return fmt.Errorf("%s not installed on system", c.shim)
@ -472,6 +473,13 @@ func (c *container) createCmd(pid string, cmd *exec.Cmd, p *process) error {
} }
return err return err
} }
go func() {
err := p.cmd.Wait()
if err == nil {
p.cmdSuccess = true
}
close(p.cmdDoneCh)
}()
if err := c.waitForCreate(p, cmd); err != nil { if err := c.waitForCreate(p, cmd); err != nil {
return err return err
} }

View file

@ -67,6 +67,7 @@ func newProcess(config *processConfig) (*process, error) {
container: config.c, container: config.c,
spec: config.processSpec, spec: config.processSpec,
stdio: config.stdio, stdio: config.stdio,
cmdDoneCh: make(chan struct{}),
} }
uid, gid, err := getRootIDs(config.spec) uid, gid, err := getRootIDs(config.spec)
if err != nil { if err != nil {
@ -148,6 +149,8 @@ type process struct {
spec specs.ProcessSpec spec specs.ProcessSpec
stdio Stdio stdio Stdio
cmd *exec.Cmd cmd *exec.Cmd
cmdSuccess bool
cmdDoneCh chan struct{}
} }
func (p *process) ID() string { func (p *process) ID() string {
@ -230,8 +233,8 @@ func (p *process) getPidFromFile() (int, error) {
// Wait will reap the shim process // Wait will reap the shim process
func (p *process) Wait() { func (p *process) Wait() {
if p.cmd != nil { if p.cmdDoneCh != nil {
p.cmd.Wait() <-p.cmdDoneCh
} }
} }
@ -262,7 +265,6 @@ func (p *process) Start() error {
if p.ID() == InitProcessID { if p.ID() == InitProcessID {
var ( var (
errC = make(chan error, 1) errC = make(chan error, 1)
shimExit = make(chan struct{}, 1)
args = append(p.container.runtimeArgs, "start", p.container.id) args = append(p.container.runtimeArgs, "start", p.container.id)
cmd = exec.Command(p.container.runtime, args...) cmd = exec.Command(p.container.runtime, args...)
) )
@ -273,20 +275,22 @@ func (p *process) Start() error {
} }
errC <- nil errC <- nil
}() }()
go func() {
p.Wait()
close(shimExit)
}()
select { select {
case err := <-errC: case err := <-errC:
if err != nil { if err != nil {
return err return err
} }
case <-shimExit: case <-p.cmdDoneCh:
if !p.cmdSuccess {
cmd.Process.Kill() cmd.Process.Kill()
cmd.Wait() cmd.Wait()
return ErrShimExited return ErrShimExited
} }
err := <-errC
if err != nil {
return err
}
}
} }
return nil return nil
} }

View file

@ -1,10 +1,10 @@
package supervisor package supervisor
import ( import (
"flag"
"os" "os"
"sort" "sort"
"testing" "testing"
"flag"
"github.com/docker/containerd/runtime" "github.com/docker/containerd/runtime"
"github.com/docker/containerd/specs" "github.com/docker/containerd/specs"
@ -71,7 +71,6 @@ func (p *testProcess) State() runtime.State {
} }
func (p *testProcess) Wait() { func (p *testProcess) Wait() {
} }
func TestSortProcesses(t *testing.T) { func TestSortProcesses(t *testing.T) {