From f543f2fbcd1eb7f7bcb0994b80da490736cd0aab Mon Sep 17 00:00:00 2001 From: Michael Crosby Date: Fri, 26 Jul 2019 19:52:03 +0000 Subject: [PATCH] Call CloseIO when stdin closes in ctr Fixes #2439 Signed-off-by: Michael Crosby --- cmd/ctr/commands/tasks/exec.go | 30 ++++++++++++++++++++++++++-- cmd/ctr/commands/tasks/tasks_unix.go | 14 +++++++++++-- 2 files changed, 40 insertions(+), 4 deletions(-) diff --git a/cmd/ctr/commands/tasks/exec.go b/cmd/ctr/commands/tasks/exec.go index 887ceee54cc6..fc18da4ac245 100644 --- a/cmd/ctr/commands/tasks/exec.go +++ b/cmd/ctr/commands/tasks/exec.go @@ -18,9 +18,12 @@ package tasks import ( "errors" + "io" "net/url" + "os" "github.com/containerd/console" + "github.com/containerd/containerd" "github.com/containerd/containerd/cio" "github.com/containerd/containerd/cmd/ctr/commands" "github.com/sirupsen/logrus" @@ -91,7 +94,12 @@ var execCommand = cli.Command{ pspec.Terminal = tty pspec.Args = args - var ioCreator cio.Creator + var ( + ioCreator cio.Creator + stdinC = &stdinCloser{ + stdin: os.Stdin, + } + ) if logURI := context.String("log-uri"); logURI != "" { uri, err := url.Parse(logURI) @@ -109,7 +117,7 @@ var execCommand = cli.Command{ ioCreator = cio.LogURI(uri) } else { - cioOpts := []cio.Opt{cio.WithStdio, cio.WithFIFODir(context.String("fifo-dir"))} + cioOpts := []cio.Opt{cio.WithStreams(stdinC, os.Stdout, os.Stderr), cio.WithFIFODir(context.String("fifo-dir"))} if tty { cioOpts = append(cioOpts, cio.WithTerminal) } @@ -120,6 +128,9 @@ var execCommand = cli.Command{ if err != nil { return err } + stdinC.closer = func() { + process.CloseIO(ctx, containerd.WithStdinCloser) + } // if detach, we should not call this defer if !detach { defer process.Delete(ctx) @@ -166,3 +177,18 @@ var execCommand = cli.Command{ return nil }, } + +type stdinCloser struct { + stdin *os.File + closer func() +} + +func (s *stdinCloser) Read(p []byte) (int, error) { + n, err := s.stdin.Read(p) + if err == io.EOF { + if s.closer != nil { + s.closer() + } + } + return n, err +} diff --git a/cmd/ctr/commands/tasks/tasks_unix.go b/cmd/ctr/commands/tasks/tasks_unix.go index 103466482fb0..12917f20172c 100644 --- a/cmd/ctr/commands/tasks/tasks_unix.go +++ b/cmd/ctr/commands/tasks/tasks_unix.go @@ -69,7 +69,10 @@ func HandleConsoleResize(ctx gocontext.Context, task resizer, con console.Consol // NewTask creates a new task func NewTask(ctx gocontext.Context, client *containerd.Client, container containerd.Container, checkpoint string, con console.Console, nullIO bool, logURI string, ioOpts []cio.Opt, opts ...containerd.NewTaskOpts) (containerd.Task, error) { - stdio := cio.NewCreator(append([]cio.Opt{cio.WithStdio}, ioOpts...)...) + stdinC := &stdinCloser{ + stdin: os.Stdin, + } + stdio := cio.NewCreator(append([]cio.Opt{cio.WithStreams(stdinC, os.Stdout, os.Stderr)}, ioOpts...)...) if checkpoint != "" { im, err := client.GetImage(ctx, checkpoint) if err != nil { @@ -94,7 +97,14 @@ func NewTask(ctx gocontext.Context, client *containerd.Client, container contain } ioCreator = cio.LogURI(u) } - return container.NewTask(ctx, ioCreator, opts...) + t, err := container.NewTask(ctx, ioCreator, opts...) + if err != nil { + return nil, err + } + stdinC.closer = func() { + t.CloseIO(ctx, containerd.WithStdinCloser) + } + return t, nil } func getNewTaskOpts(context *cli.Context) []containerd.NewTaskOpts {