Merge pull request #1603 from mlaventure/fix-windows-flaky-tests

windows: ensure a init process exist after "Create()"
This commit is contained in:
Michael Crosby 2017-10-09 11:58:23 -04:00 committed by GitHub
commit 72bb45ac46
4 changed files with 46 additions and 19 deletions

View File

@ -203,9 +203,9 @@ func TestContainerOutput(t *testing.T) {
} }
status := <-statusC status := <-statusC
code, _, _ := status.Result() code, _, err := status.Result()
if code != 0 { if code != 0 {
t.Errorf("expected status 0 but received %d", code) t.Errorf("expected status 0 but received %d: %v", code, err)
} }
if _, err := task.Delete(ctx); err != nil { if _, err := task.Delete(ctx); err != nil {
t.Error(err) t.Error(err)

View File

@ -5,6 +5,7 @@ package windows
import ( import (
"context" "context"
"io" "io"
"sync"
"syscall" "syscall"
"time" "time"
@ -19,13 +20,14 @@ import (
// process implements containerd.Process and containerd.State // process implements containerd.Process and containerd.State
type process struct { type process struct {
sync.Mutex
hcs hcsshim.Process hcs hcsshim.Process
id string id string
pid uint32 pid uint32
io *pipeSet io *pipeSet
status runtime.Status task *task
task *task
exitCh chan struct{} exitCh chan struct{}
exitCode uint32 exitCode uint32
@ -50,6 +52,9 @@ func (p *process) State(ctx context.Context) (runtime.State, error) {
} }
func (p *process) Status() runtime.Status { func (p *process) Status() runtime.Status {
p.Lock()
defer p.Unlock()
if p.task.getStatus() == runtime.PausedStatus { if p.task.getStatus() == runtime.PausedStatus {
return runtime.PausedStatus return runtime.PausedStatus
} }
@ -69,15 +74,24 @@ func (p *process) Status() runtime.Status {
func (p *process) Kill(ctx context.Context, sig uint32, all bool) error { func (p *process) Kill(ctx context.Context, sig uint32, all bool) error {
// On windows all signals kill the process // On windows all signals kill the process
if p.Status() == runtime.CreatedStatus {
return errors.Wrap(errdefs.ErrFailedPrecondition, "process was not started")
}
return errors.Wrap(p.hcs.Kill(), "failed to kill process") return errors.Wrap(p.hcs.Kill(), "failed to kill process")
} }
func (p *process) ResizePty(ctx context.Context, size runtime.ConsoleSize) error { func (p *process) ResizePty(ctx context.Context, size runtime.ConsoleSize) error {
if p.Status() == runtime.CreatedStatus {
return errors.Wrap(errdefs.ErrFailedPrecondition, "process was not started")
}
err := p.hcs.ResizeConsole(uint16(size.Width), uint16(size.Height)) err := p.hcs.ResizeConsole(uint16(size.Width), uint16(size.Height))
return errors.Wrap(err, "failed to resize process console") return errors.Wrap(err, "failed to resize process console")
} }
func (p *process) CloseIO(ctx context.Context) error { func (p *process) CloseIO(ctx context.Context) error {
if p.Status() == runtime.CreatedStatus {
return errors.Wrap(errdefs.ErrFailedPrecondition, "process was not started")
}
return errors.Wrap(p.hcs.CloseStdin(), "failed to close stdin") return errors.Wrap(p.hcs.CloseStdin(), "failed to close stdin")
} }
@ -93,6 +107,13 @@ func (p *process) ExitCode() (uint32, time.Time, error) {
} }
func (p *process) Start(ctx context.Context) (err error) { func (p *process) Start(ctx context.Context) (err error) {
p.Lock()
defer p.Unlock()
if p.hcs != nil {
return errors.Wrap(errdefs.ErrFailedPrecondition, "process already started")
}
// If we fail, close the io right now // If we fail, close the io right now
defer func() { defer func() {
if err != nil { if err != nil {
@ -132,6 +153,7 @@ func (p *process) Start(ctx context.Context) (err error) {
if p.io.stderr != nil { if p.io.stderr != nil {
go ioCopy("stderr", p.io.stderr, stderr) go ioCopy("stderr", p.io.stderr, stderr)
} }
p.hcs = hp
// Wait for the process to exit to get the exit status // Wait for the process to exit to get the exit status
go func() { go func() {
@ -174,8 +196,6 @@ func (p *process) Start(ctx context.Context) (err error) {
// Cleanup HCS resources // Cleanup HCS resources
hp.Close() hp.Close()
}() }()
p.status = runtime.RunningStatus
p.hcs = hp
return nil return nil
} }

View File

@ -304,6 +304,11 @@ func (r *windowsRuntime) newTask(ctx context.Context, namespace, id string, spec
hcsContainer: ctr, hcsContainer: ctr,
terminateDuration: createOpts.TerminateDuration, terminateDuration: createOpts.TerminateDuration,
} }
// Create the new process but don't start it
pconf := newWindowsProcessConfig(t.spec.Process, t.io)
if _, err = t.newProcess(ctx, t.id, pconf, t.io); err != nil {
return nil, err
}
r.tasks.Add(ctx, t) r.tasks.Add(ctx, t)
var rootfs []*containerdtypes.Mount var rootfs []*containerdtypes.Mount

View File

@ -111,13 +111,16 @@ func (t *task) Info() runtime.TaskInfo {
} }
func (t *task) Start(ctx context.Context) error { func (t *task) Start(ctx context.Context) error {
conf := newWindowsProcessConfig(t.spec.Process, t.io) p := t.getProcess(t.id)
p, err := t.newProcess(ctx, t.id, conf, t.io) if p == nil {
if err != nil { panic("init process is missing")
return err
} }
if p.Status() != runtime.CreatedStatus {
return errors.Wrap(errdefs.ErrFailedPrecondition, "process was already started")
}
if err := p.Start(ctx); err != nil { if err := p.Start(ctx); err != nil {
t.removeProcess(t.id)
return err return err
} }
t.publisher.Publish(ctx, t.publisher.Publish(ctx,
@ -136,13 +139,13 @@ func (t *task) Pause(ctx context.Context) error {
t.Lock() t.Lock()
t.status = runtime.PausedStatus t.status = runtime.PausedStatus
t.Unlock() t.Unlock()
}
if err == nil {
t.publisher.Publish(ctx, t.publisher.Publish(ctx,
runtime.TaskPausedEventTopic, runtime.TaskPausedEventTopic,
&eventsapi.TaskPaused{ &eventsapi.TaskPaused{
ContainerID: t.id, ContainerID: t.id,
}) })
return nil
} }
return errors.Wrap(err, "hcsshim failed to pause task") return errors.Wrap(err, "hcsshim failed to pause task")
} }
@ -157,13 +160,13 @@ func (t *task) Resume(ctx context.Context) error {
t.Lock() t.Lock()
t.status = runtime.RunningStatus t.status = runtime.RunningStatus
t.Unlock() t.Unlock()
}
if err == nil {
t.publisher.Publish(ctx, t.publisher.Publish(ctx,
runtime.TaskResumedEventTopic, runtime.TaskResumedEventTopic,
&eventsapi.TaskResumed{ &eventsapi.TaskResumed{
ContainerID: t.id, ContainerID: t.id,
}) })
return nil
} }
return errors.Wrap(err, "hcsshim failed to resume task") return errors.Wrap(err, "hcsshim failed to resume task")
} }
@ -313,7 +316,6 @@ func (t *task) newProcess(ctx context.Context, id string, conf *hcsshim.ProcessC
id: id, id: id,
pid: pid, pid: pid,
io: pset, io: pset,
status: runtime.CreatedStatus,
task: t, task: t,
exitCh: make(chan struct{}), exitCh: make(chan struct{}),
conf: conf, conf: conf,