Update windows with exec create/start actions
Signed-off-by: Michael Crosby <crosbymichael@gmail.com>
This commit is contained in:
		| @@ -4,12 +4,17 @@ package windows | ||||
|  | ||||
| import ( | ||||
| 	"context" | ||||
| 	"io" | ||||
| 	"syscall" | ||||
| 	"time" | ||||
|  | ||||
| 	"github.com/Microsoft/hcsshim" | ||||
| 	eventsapi "github.com/containerd/containerd/api/services/events/v1" | ||||
| 	"github.com/containerd/containerd/errdefs" | ||||
| 	"github.com/containerd/containerd/log" | ||||
| 	"github.com/containerd/containerd/runtime" | ||||
| 	"github.com/pkg/errors" | ||||
| 	"github.com/sirupsen/logrus" | ||||
| ) | ||||
|  | ||||
| // process implements containerd.Process and containerd.State | ||||
| @@ -25,6 +30,7 @@ type process struct { | ||||
| 	exitCh   chan struct{} | ||||
| 	exitCode uint32 | ||||
| 	exitTime time.Time | ||||
| 	conf     *hcsshim.ProcessConfig | ||||
| } | ||||
|  | ||||
| func (p *process) ID() string { | ||||
| @@ -81,3 +87,83 @@ func (p *process) ExitCode() (uint32, time.Time, error) { | ||||
| 	} | ||||
| 	return p.exitCode, p.exitTime, nil | ||||
| } | ||||
|  | ||||
| func (p *process) Start(ctx context.Context) (err error) { | ||||
| 	var hp hcsshim.Process | ||||
| 	if hp, err = p.task.hcsContainer.CreateProcess(p.conf); err != nil { | ||||
| 		return errors.Wrapf(err, "failed to create process") | ||||
| 	} | ||||
|  | ||||
| 	stdin, stdout, stderr, err := hp.Stdio() | ||||
| 	if err != nil { | ||||
| 		hp.Kill() | ||||
| 		return errors.Wrapf(err, "failed to retrieve init process stdio") | ||||
| 	} | ||||
|  | ||||
| 	ioCopy := func(name string, dst io.WriteCloser, src io.ReadCloser) { | ||||
| 		log.G(ctx).WithFields(logrus.Fields{"id": p.id, "pid": p.pid}). | ||||
| 			Debugf("%s: copy started", name) | ||||
| 		io.Copy(dst, src) | ||||
| 		log.G(ctx).WithFields(logrus.Fields{"id": p.id, "pid": p.pid}). | ||||
| 			Debugf("%s: copy done", name) | ||||
| 		dst.Close() | ||||
| 		src.Close() | ||||
| 	} | ||||
|  | ||||
| 	if p.io.stdin != nil { | ||||
| 		go ioCopy("stdin", stdin, p.io.stdin) | ||||
| 	} | ||||
|  | ||||
| 	if p.io.stdout != nil { | ||||
| 		go ioCopy("stdout", p.io.stdout, stdout) | ||||
| 	} | ||||
|  | ||||
| 	if p.io.stderr != nil { | ||||
| 		go ioCopy("stderr", p.io.stderr, stderr) | ||||
| 	} | ||||
|  | ||||
| 	// Wait for the process to exit to get the exit status | ||||
| 	go func() { | ||||
| 		if err := hp.Wait(); err != nil { | ||||
| 			herr, ok := err.(*hcsshim.ProcessError) | ||||
| 			if ok && herr.Err != syscall.ERROR_BROKEN_PIPE { | ||||
| 				log.G(ctx). | ||||
| 					WithError(err). | ||||
| 					WithFields(logrus.Fields{"id": p.id, "pid": p.pid}). | ||||
| 					Warnf("hcsshim wait failed (process may have been killed)") | ||||
| 			} | ||||
| 			// Try to get the exit code nonetheless | ||||
| 		} | ||||
| 		p.exitTime = time.Now() | ||||
|  | ||||
| 		ec, err := hp.ExitCode() | ||||
| 		if err != nil { | ||||
| 			log.G(ctx). | ||||
| 				WithError(err). | ||||
| 				WithFields(logrus.Fields{"id": p.id, "pid": p.pid}). | ||||
| 				Warnf("hcsshim could not retrieve exit code") | ||||
| 			// Use the unknown exit code | ||||
| 			ec = 255 | ||||
| 		} | ||||
| 		p.exitCode = uint32(ec) | ||||
|  | ||||
| 		p.task.publisher.Publish(ctx, | ||||
| 			runtime.TaskExitEventTopic, | ||||
| 			&eventsapi.TaskExit{ | ||||
| 				ContainerID: p.task.id, | ||||
| 				ID:          p.id, | ||||
| 				Pid:         p.pid, | ||||
| 				ExitStatus:  p.exitCode, | ||||
| 				ExitedAt:    p.exitTime, | ||||
| 			}) | ||||
|  | ||||
| 		close(p.exitCh) | ||||
| 		// Ensure io's are closed | ||||
| 		p.io.Close() | ||||
| 		// Cleanup HCS resources | ||||
| 		hp.Close() | ||||
| 	}() | ||||
| 	p.status = runtime.RunningStatus | ||||
| 	p.hcs = hp | ||||
| 	return nil | ||||
| } | ||||
|   | ||||
| @@ -4,22 +4,18 @@ package windows | ||||
|  | ||||
| import ( | ||||
| 	"context" | ||||
| 	"io" | ||||
| 	"sync" | ||||
| 	"syscall" | ||||
| 	"time" | ||||
|  | ||||
| 	"github.com/Microsoft/hcsshim" | ||||
| 	eventsapi "github.com/containerd/containerd/api/services/events/v1" | ||||
| 	"github.com/containerd/containerd/errdefs" | ||||
| 	"github.com/containerd/containerd/events" | ||||
| 	"github.com/containerd/containerd/log" | ||||
| 	"github.com/containerd/containerd/runtime" | ||||
| 	"github.com/containerd/containerd/typeurl" | ||||
| 	"github.com/gogo/protobuf/types" | ||||
| 	specs "github.com/opencontainers/runtime-spec/specs-go" | ||||
| 	"github.com/pkg/errors" | ||||
| 	"github.com/sirupsen/logrus" | ||||
| ) | ||||
|  | ||||
| type task struct { | ||||
| @@ -203,7 +199,6 @@ func (t *task) Exec(ctx context.Context, id string, opts runtime.ExecOpts) (runt | ||||
| 		&eventsapi.TaskExecAdded{ | ||||
| 			ContainerID: t.id, | ||||
| 			ExecID:      id, | ||||
| 			Pid:         p.Pid(), | ||||
| 		}) | ||||
|  | ||||
| 	return p, nil | ||||
| @@ -290,95 +285,18 @@ func (t *task) newProcess(ctx context.Context, id string, conf *hcsshim.ProcessC | ||||
| 		}() | ||||
| 	} | ||||
| 	t.Unlock() | ||||
|  | ||||
| 	var p hcsshim.Process | ||||
| 	if p, err = t.hcsContainer.CreateProcess(conf); err != nil { | ||||
| 		return nil, errors.Wrapf(err, "failed to create process") | ||||
| 	} | ||||
|  | ||||
| 	stdin, stdout, stderr, err := p.Stdio() | ||||
| 	if err != nil { | ||||
| 		p.Kill() | ||||
| 		return nil, errors.Wrapf(err, "failed to retrieve init process stdio") | ||||
| 	} | ||||
|  | ||||
| 	ioCopy := func(name string, dst io.WriteCloser, src io.ReadCloser) { | ||||
| 		log.G(ctx).WithFields(logrus.Fields{"id": id, "pid": pid}). | ||||
| 			Debugf("%s: copy started", name) | ||||
| 		io.Copy(dst, src) | ||||
| 		log.G(ctx).WithFields(logrus.Fields{"id": id, "pid": pid}). | ||||
| 			Debugf("%s: copy done", name) | ||||
| 		dst.Close() | ||||
| 		src.Close() | ||||
| 	} | ||||
|  | ||||
| 	if pset.stdin != nil { | ||||
| 		go ioCopy("stdin", stdin, pset.stdin) | ||||
| 	} | ||||
|  | ||||
| 	if pset.stdout != nil { | ||||
| 		go ioCopy("stdout", pset.stdout, stdout) | ||||
| 	} | ||||
|  | ||||
| 	if pset.stderr != nil { | ||||
| 		go ioCopy("stderr", pset.stderr, stderr) | ||||
| 	} | ||||
|  | ||||
| 	t.Lock() | ||||
| 	wp := &process{ | ||||
| 		id:     id, | ||||
| 		pid:    pid, | ||||
| 		io:     pset, | ||||
| 		status: runtime.RunningStatus, | ||||
| 		status: runtime.CreatedStatus, | ||||
| 		task:   t, | ||||
| 		hcs:    p, | ||||
| 		exitCh: make(chan struct{}), | ||||
| 	} | ||||
| 	t.processes[id] = wp | ||||
| 	t.Unlock() | ||||
|  | ||||
| 	// Wait for the process to exit to get the exit status | ||||
| 	go func() { | ||||
| 		if err := p.Wait(); err != nil { | ||||
| 			herr, ok := err.(*hcsshim.ProcessError) | ||||
| 			if ok && herr.Err != syscall.ERROR_BROKEN_PIPE { | ||||
| 				log.G(ctx). | ||||
| 					WithError(err). | ||||
| 					WithFields(logrus.Fields{"id": id, "pid": pid}). | ||||
| 					Warnf("hcsshim wait failed (process may have been killed)") | ||||
| 			} | ||||
| 			// Try to get the exit code nonetheless | ||||
| 		} | ||||
| 		wp.exitTime = time.Now() | ||||
|  | ||||
| 		ec, err := p.ExitCode() | ||||
| 		if err != nil { | ||||
| 			log.G(ctx). | ||||
| 				WithError(err). | ||||
| 				WithFields(logrus.Fields{"id": id, "pid": pid}). | ||||
| 				Warnf("hcsshim could not retrieve exit code") | ||||
| 			// Use the unknown exit code | ||||
| 			ec = 255 | ||||
| 		} | ||||
| 		wp.exitCode = uint32(ec) | ||||
|  | ||||
| 		t.publisher.Publish(ctx, | ||||
| 			runtime.TaskExitEventTopic, | ||||
| 			&eventsapi.TaskExit{ | ||||
| 				ContainerID: t.id, | ||||
| 				ID:          id, | ||||
| 				Pid:         pid, | ||||
| 				ExitStatus:  wp.exitCode, | ||||
| 				ExitedAt:    wp.exitTime, | ||||
| 			}) | ||||
|  | ||||
| 		close(wp.exitCh) | ||||
| 		// Ensure io's are closed | ||||
| 		pset.Close() | ||||
| 		// Cleanup HCS resources | ||||
| 		p.Close() | ||||
| 	}() | ||||
|  | ||||
| 	return wp, nil | ||||
| } | ||||
|  | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 Michael Crosby
					Michael Crosby