Return exit status from Wait of stopped process

This changes Wait() from returning an error whenever you call wait on a
stopped process/task to returning the exit status from the process.

This also adds the exit status to the Status() call on a process/task so
that a user can Wait(), check status, then cancel the wait to avoid
races in event handling.

Signed-off-by: Michael Crosby <crosbymichael@gmail.com>
This commit is contained in:
Michael Crosby
2017-08-03 17:09:16 -04:00
parent 0fa76584f8
commit 9f13b414b9
16 changed files with 283 additions and 178 deletions

33
task.go
View File

@@ -28,14 +28,19 @@ import (
const UnknownExitStatus = 255
type Status string
type Status struct {
Status ProcessStatus
ExitStatus uint32
}
type ProcessStatus string
const (
Running Status = "running"
Created Status = "created"
Stopped Status = "stopped"
Paused Status = "paused"
Pausing Status = "pausing"
Running ProcessStatus = "running"
Created ProcessStatus = "created"
Stopped ProcessStatus = "stopped"
Paused ProcessStatus = "paused"
Pausing ProcessStatus = "pausing"
)
type IOCloseInfo struct {
@@ -146,12 +151,14 @@ func (t *task) Status(ctx context.Context) (Status, error) {
ContainerID: t.id,
})
if err != nil {
return "", errdefs.FromGRPC(err)
return Status{}, errdefs.FromGRPC(err)
}
return Status(strings.ToLower(r.Process.Status.String())), nil
return Status{
Status: ProcessStatus(strings.ToLower(r.Process.Status.String())),
ExitStatus: r.Process.ExitStatus,
}, nil
}
// Wait is a blocking call that will wait for the task to exit and return the exit status
func (t *task) Wait(ctx context.Context) (uint32, error) {
eventstream, err := t.client.EventService().Subscribe(ctx, &eventsapi.SubscribeRequest{
Filters: []string{"topic==" + runtime.TaskExitEventTopic},
@@ -160,8 +167,12 @@ func (t *task) Wait(ctx context.Context) (uint32, error) {
return UnknownExitStatus, errdefs.FromGRPC(err)
}
// first check if the task has exited
if status, _ := t.Status(ctx); status == Stopped {
return UnknownExitStatus, errdefs.ErrUnavailable
status, err := t.Status(ctx)
if err != nil {
return UnknownExitStatus, errdefs.FromGRPC(err)
}
if status.Status == Stopped {
return status.ExitStatus, nil
}
for {
evt, err := eventstream.Recv()