Browse code

Remove libcontainerd.IOPipe

replaced with cio.DirectIO

Signed-off-by: Daniel Nephin <dnephin@docker.com>

Daniel Nephin authored on 2017/12/08 04:26:27
Showing 13 changed files
... ...
@@ -27,7 +27,6 @@ import (
27 27
 	"github.com/docker/docker/daemon/network"
28 28
 	"github.com/docker/docker/image"
29 29
 	"github.com/docker/docker/layer"
30
-	"github.com/docker/docker/libcontainerd"
31 30
 	"github.com/docker/docker/opts"
32 31
 	"github.com/docker/docker/pkg/containerfs"
33 32
 	"github.com/docker/docker/pkg/idtools"
... ...
@@ -1004,7 +1003,7 @@ func (container *Container) CloseStreams() error {
1004 1004
 }
1005 1005
 
1006 1006
 // InitializeStdio is called by libcontainerd to connect the stdio.
1007
-func (container *Container) InitializeStdio(iop *libcontainerd.IOPipe) (cio.IO, error) {
1007
+func (container *Container) InitializeStdio(iop *cio.DirectIO) (cio.IO, error) {
1008 1008
 	if err := container.startLogging(); err != nil {
1009 1009
 		container.Reset(false)
1010 1010
 		return nil, err
... ...
@@ -7,7 +7,7 @@ import (
7 7
 	"strings"
8 8
 	"sync"
9 9
 
10
-	"github.com/docker/docker/libcontainerd"
10
+	"github.com/containerd/containerd/cio"
11 11
 	"github.com/docker/docker/pkg/broadcaster"
12 12
 	"github.com/docker/docker/pkg/ioutils"
13 13
 	"github.com/docker/docker/pkg/pools"
... ...
@@ -114,7 +114,7 @@ func (c *Config) CloseStreams() error {
114 114
 }
115 115
 
116 116
 // CopyToPipe connects streamconfig with a libcontainerd.IOPipe
117
-func (c *Config) CopyToPipe(iop *libcontainerd.IOPipe) {
117
+func (c *Config) CopyToPipe(iop *cio.DirectIO) {
118 118
 	copyFunc := func(w io.Writer, r io.ReadCloser) {
119 119
 		c.Add(1)
120 120
 		go func() {
... ...
@@ -6,7 +6,6 @@ import (
6 6
 
7 7
 	"github.com/containerd/containerd/cio"
8 8
 	"github.com/docker/docker/container/stream"
9
-	"github.com/docker/docker/libcontainerd"
10 9
 	"github.com/docker/docker/pkg/stringid"
11 10
 	"github.com/sirupsen/logrus"
12 11
 )
... ...
@@ -63,7 +62,7 @@ func (i *rio) Wait() {
63 63
 }
64 64
 
65 65
 // InitializeStdio is called by libcontainerd to connect the stdio.
66
-func (c *Config) InitializeStdio(iop *libcontainerd.IOPipe) (cio.IO, error) {
66
+func (c *Config) InitializeStdio(iop *cio.DirectIO) (cio.IO, error) {
67 67
 	c.StreamConfig.CopyToPipe(iop)
68 68
 
69 69
 	if c.StreamConfig.Stdin() == nil && !c.Tty && runtime.GOOS == "windows" {
... ...
@@ -121,7 +121,7 @@ func (c *client) Restore(ctx context.Context, id string, attachStdio StdioCallba
121 121
 	c.Lock()
122 122
 	defer c.Unlock()
123 123
 
124
-	var rio cio.IO
124
+	var rio *cio.DirectIO
125 125
 	defer func() {
126 126
 		err = wrapError(err)
127 127
 	}()
... ...
@@ -139,13 +139,12 @@ func (c *client) Restore(ctx context.Context, id string, attachStdio StdioCallba
139 139
 	}()
140 140
 
141 141
 	t, err := ctr.Task(ctx, func(fifos *cio.FIFOSet) (cio.IO, error) {
142
-		io, err := newIOPipe(fifos)
142
+		rio, err = cio.NewDirectIO(ctx, fifos)
143 143
 		if err != nil {
144 144
 			return nil, err
145 145
 		}
146 146
 
147
-		rio, err = attachStdio(io)
148
-		return rio, err
147
+		return attachStdio(rio)
149 148
 	})
150 149
 	if err != nil && !errdefs.IsNotFound(errors.Cause(err)) {
151 150
 		return false, -1, err
... ...
@@ -255,7 +254,7 @@ func (c *client) Start(ctx context.Context, id, checkpointDir string, withStdin
255 255
 	uid, gid := getSpecUser(spec)
256 256
 	t, err = ctr.ctr.NewTask(ctx,
257 257
 		func(id string) (cio.IO, error) {
258
-			fifos := newFIFOSet(ctr.bundleDir, id, InitProcessName, withStdin, spec.Process.Terminal)
258
+			fifos := newFIFOSet(ctr.bundleDir, InitProcessName, withStdin, spec.Process.Terminal)
259 259
 			rio, err = c.createIO(fifos, id, InitProcessName, stdinCloseSync, attachStdio)
260 260
 			return rio, err
261 261
 		},
... ...
@@ -315,7 +314,7 @@ func (c *client) Exec(ctx context.Context, containerID, processID string, spec *
315 315
 		stdinCloseSync = make(chan struct{})
316 316
 	)
317 317
 
318
-	fifos := newFIFOSet(ctr.bundleDir, containerID, processID, withStdin, spec.Terminal)
318
+	fifos := newFIFOSet(ctr.bundleDir, processID, withStdin, spec.Terminal)
319 319
 
320 320
 	defer func() {
321 321
 		if err != nil {
... ...
@@ -612,7 +611,7 @@ func (c *client) getProcess(containerID, processID string) (containerd.Process,
612 612
 // createIO creates the io to be used by a process
613 613
 // This needs to get a pointer to interface as upon closure the process may not have yet been registered
614 614
 func (c *client) createIO(fifos *cio.FIFOSet, containerID, processID string, stdinCloseSync chan struct{}, attachStdio StdioCallback) (cio.IO, error) {
615
-	io, err := newIOPipe(fifos)
615
+	io, err := cio.NewDirectIO(context.Background(), fifos)
616 616
 	if err != nil {
617 617
 		return nil, err
618 618
 	}
... ...
@@ -687,7 +686,7 @@ func (c *client) processEvent(ctr *container, et EventType, ei EventInfo) {
687 687
 					"container": ei.ContainerID,
688 688
 				}).Error("failed to find container")
689 689
 			} else {
690
-				rmFIFOSet(newFIFOSet(ctr.bundleDir, ei.ContainerID, ei.ProcessID, true, false))
690
+				rmFIFOSet(newFIFOSet(ctr.bundleDir, ei.ProcessID, true, false))
691 691
 			}
692 692
 		}
693 693
 	})
... ...
@@ -80,25 +80,27 @@ func prepareBundleDir(bundleDir string, ociSpec *specs.Spec) (string, error) {
80 80
 	return p, nil
81 81
 }
82 82
 
83
-func newFIFOSet(bundleDir, containerID, processID string, withStdin, withTerminal bool) *cio.FIFOSet {
83
+func newFIFOSet(bundleDir, processID string, withStdin, withTerminal bool) *cio.FIFOSet {
84 84
 	fifos := &cio.FIFOSet{
85
-		Terminal: withTerminal,
86
-		Out:      filepath.Join(bundleDir, processID+"-stdout"),
85
+		Config: cio.Config{
86
+			Terminal: withTerminal,
87
+			Stdout:   filepath.Join(bundleDir, processID+"-stdout"),
88
+		},
87 89
 	}
88 90
 
89 91
 	if withStdin {
90
-		fifos.In = filepath.Join(bundleDir, processID+"-stdin")
92
+		fifos.Stdin = filepath.Join(bundleDir, processID+"-stdin")
91 93
 	}
92 94
 
93 95
 	if !fifos.Terminal {
94
-		fifos.Err = filepath.Join(bundleDir, processID+"-stderr")
96
+		fifos.Stderr = filepath.Join(bundleDir, processID+"-stderr")
95 97
 	}
96 98
 
97 99
 	return fifos
98 100
 }
99 101
 
100 102
 func rmFIFOSet(fset *cio.FIFOSet) {
101
-	for _, fn := range []string{fset.Out, fset.In, fset.Err} {
103
+	for _, fn := range []string{fset.Stdout, fset.Stdin, fset.Stderr} {
102 104
 		if fn != "" {
103 105
 			if err := os.RemoveAll(fn); err != nil {
104 106
 				logrus.Warnf("libcontainerd: failed to remove fifo %v: %v", fn, err)
... ...
@@ -18,6 +18,7 @@ import (
18 18
 	"github.com/Microsoft/hcsshim"
19 19
 	opengcs "github.com/Microsoft/opengcs/client"
20 20
 	"github.com/containerd/containerd"
21
+	"github.com/containerd/containerd/cio"
21 22
 	"github.com/docker/docker/pkg/sysinfo"
22 23
 	"github.com/docker/docker/pkg/system"
23 24
 	specs "github.com/opencontainers/runtime-spec/specs-go"
... ...
@@ -670,28 +671,12 @@ func (c *client) Start(_ context.Context, id, _ string, withStdin bool, attachSt
670 670
 		return p.pid, nil
671 671
 	}
672 672
 
673
-	var (
674
-		stdout, stderr io.ReadCloser
675
-		stdin          io.WriteCloser
676
-	)
677
-	stdin, stdout, stderr, err = newProcess.Stdio()
673
+	dio, err := newIOFromProcess(newProcess)
678 674
 	if err != nil {
679 675
 		logger.WithError(err).Error("failed to get stdio pipes")
680 676
 		return -1, err
681 677
 	}
682
-
683
-	iopipe := &IOPipe{Terminal: ctr.ociSpec.Process.Terminal}
684
-	iopipe.Stdin = createStdInCloser(stdin, newProcess)
685
-
686
-	// Convert io.ReadClosers to io.Readers
687
-	if stdout != nil {
688
-		iopipe.Stdout = ioutil.NopCloser(&autoClosingReader{ReadCloser: stdout})
689
-	}
690
-	if stderr != nil {
691
-		iopipe.Stderr = ioutil.NopCloser(&autoClosingReader{ReadCloser: stderr})
692
-	}
693
-
694
-	_, err = attachStdio(iopipe)
678
+	_, err = attachStdio(dio)
695 679
 	if err != nil {
696 680
 		logger.WithError(err).Error("failed to attache stdio")
697 681
 		return -1, err
... ...
@@ -727,6 +712,26 @@ func (c *client) Start(_ context.Context, id, _ string, withStdin bool, attachSt
727 727
 	return p.pid, nil
728 728
 }
729 729
 
730
+func newIOFromProcess(newProcess process) (*cio.DirectIO, error) {
731
+	stdin, stdout, stderr, err := newProcess.Stdio()
732
+	if err != nil {
733
+		return nil, err
734
+	}
735
+
736
+	dio := cio.DirectIO{
737
+		Terminal: ctr.ociSpec.Process.Terminal,
738
+		Stdin:    createStdInCloser(stdin, newProcess),
739
+	}
740
+	// Convert io.ReadClosers to io.Readers
741
+	if stdout != nil {
742
+		dio.Stdout = ioutil.NopCloser(&autoClosingReader{ReadCloser: stdout})
743
+	}
744
+	if stderr != nil {
745
+		dio.Stderr = ioutil.NopCloser(&autoClosingReader{ReadCloser: stderr})
746
+	}
747
+	return dio, nil
748
+}
749
+
730 750
 // Exec adds a process in an running container
731 751
 func (c *client) Exec(ctx context.Context, containerID, processID string, spec *specs.Process, withStdin bool, attachStdio StdioCallback) (int, error) {
732 752
 	ctr := c.getContainer(containerID)
... ...
@@ -807,25 +812,14 @@ func (c *client) Exec(ctx context.Context, containerID, processID string, spec *
807 807
 		}
808 808
 	}()
809 809
 
810
-	stdin, stdout, stderr, err = newProcess.Stdio()
810
+	dio, err := newIOFromProcess(newProcess)
811 811
 	if err != nil {
812
-		logger.WithError(err).Error("getting std pipes failed")
812
+		logger.WithError(err).Error("failed to get stdio pipes")
813 813
 		return -1, err
814 814
 	}
815
-
816
-	iopipe := &IOPipe{Terminal: spec.Terminal}
817
-	iopipe.Stdin = createStdInCloser(stdin, newProcess)
818
-
819
-	// Convert io.ReadClosers to io.Readers
820
-	if stdout != nil {
821
-		iopipe.Stdout = ioutil.NopCloser(&autoClosingReader{ReadCloser: stdout})
822
-	}
823
-	if stderr != nil {
824
-		iopipe.Stderr = ioutil.NopCloser(&autoClosingReader{ReadCloser: stderr})
825
-	}
826
-
815
+	dio.Termainl = spec.Terminal
827 816
 	// Tell the engine to attach streams back to the client
828
-	_, err = attachStdio(iopipe)
817
+	_, err = attachStdio(dio)
829 818
 	if err != nil {
830 819
 		return -1, err
831 820
 	}
832 821
deleted file mode 100644
... ...
@@ -1,36 +0,0 @@
1
-package libcontainerd
2
-
3
-import "github.com/containerd/containerd/cio"
4
-
5
-// Config returns the containerd.IOConfig of this pipe set
6
-func (p *IOPipe) Config() cio.Config {
7
-	return p.config
8
-}
9
-
10
-// Cancel aborts ongoing operations if they have not completed yet
11
-func (p *IOPipe) Cancel() {
12
-	p.cancel()
13
-}
14
-
15
-// Wait waits for io operations to finish
16
-func (p *IOPipe) Wait() {
17
-}
18
-
19
-// Close closes the underlying pipes
20
-func (p *IOPipe) Close() error {
21
-	p.cancel()
22
-
23
-	if p.Stdin != nil {
24
-		p.Stdin.Close()
25
-	}
26
-
27
-	if p.Stdout != nil {
28
-		p.Stdout.Close()
29
-	}
30
-
31
-	if p.Stderr != nil {
32
-		p.Stderr.Close()
33
-	}
34
-
35
-	return nil
36
-}
37 1
deleted file mode 100644
... ...
@@ -1,60 +0,0 @@
1
-// +build !windows
2
-
3
-package libcontainerd
4
-
5
-import (
6
-	"context"
7
-	"io"
8
-	"syscall"
9
-
10
-	"github.com/containerd/containerd/cio"
11
-	"github.com/containerd/fifo"
12
-	"github.com/pkg/errors"
13
-)
14
-
15
-func newIOPipe(fifos *cio.FIFOSet) (*IOPipe, error) {
16
-	var (
17
-		err         error
18
-		ctx, cancel = context.WithCancel(context.Background())
19
-		f           io.ReadWriteCloser
20
-		iop         = &IOPipe{
21
-			Terminal: fifos.Terminal,
22
-			cancel:   cancel,
23
-			config: cio.Config{
24
-				Terminal: fifos.Terminal,
25
-				Stdin:    fifos.In,
26
-				Stdout:   fifos.Out,
27
-				Stderr:   fifos.Err,
28
-			},
29
-		}
30
-	)
31
-	defer func() {
32
-		if err != nil {
33
-			cancel()
34
-			iop.Close()
35
-		}
36
-	}()
37
-
38
-	if fifos.In != "" {
39
-		if f, err = fifo.OpenFifo(ctx, fifos.In, syscall.O_WRONLY|syscall.O_CREAT|syscall.O_NONBLOCK, 0700); err != nil {
40
-			return nil, errors.WithStack(err)
41
-		}
42
-		iop.Stdin = f
43
-	}
44
-
45
-	if fifos.Out != "" {
46
-		if f, err = fifo.OpenFifo(ctx, fifos.Out, syscall.O_RDONLY|syscall.O_CREAT|syscall.O_NONBLOCK, 0700); err != nil {
47
-			return nil, errors.WithStack(err)
48
-		}
49
-		iop.Stdout = f
50
-	}
51
-
52
-	if fifos.Err != "" {
53
-		if f, err = fifo.OpenFifo(ctx, fifos.Err, syscall.O_RDONLY|syscall.O_CREAT|syscall.O_NONBLOCK, 0700); err != nil {
54
-			return nil, errors.WithStack(err)
55
-		}
56
-		iop.Stderr = f
57
-	}
58
-
59
-	return iop, nil
60
-}
61 1
deleted file mode 100644
... ...
@@ -1,138 +0,0 @@
1
-package libcontainerd
2
-
3
-import (
4
-	"context"
5
-	"io"
6
-	"net"
7
-	"sync"
8
-
9
-	winio "github.com/Microsoft/go-winio"
10
-	"github.com/containerd/containerd/cio"
11
-	"github.com/pkg/errors"
12
-)
13
-
14
-type winpipe struct {
15
-	sync.Mutex
16
-
17
-	ctx      context.Context
18
-	listener net.Listener
19
-	readyCh  chan struct{}
20
-	readyErr error
21
-
22
-	client net.Conn
23
-}
24
-
25
-func newWinpipe(ctx context.Context, pipe string) (*winpipe, error) {
26
-	l, err := winio.ListenPipe(pipe, nil)
27
-	if err != nil {
28
-		return nil, errors.Wrapf(err, "%q pipe creation failed", pipe)
29
-	}
30
-	wp := &winpipe{
31
-		ctx:      ctx,
32
-		listener: l,
33
-		readyCh:  make(chan struct{}),
34
-	}
35
-	go func() {
36
-		go func() {
37
-			defer close(wp.readyCh)
38
-			defer wp.listener.Close()
39
-			c, err := wp.listener.Accept()
40
-			if err != nil {
41
-				wp.Lock()
42
-				if wp.readyErr == nil {
43
-					wp.readyErr = err
44
-				}
45
-				wp.Unlock()
46
-				return
47
-			}
48
-			wp.client = c
49
-		}()
50
-
51
-		select {
52
-		case <-wp.readyCh:
53
-		case <-ctx.Done():
54
-			wp.Lock()
55
-			if wp.readyErr == nil {
56
-				wp.listener.Close()
57
-				wp.readyErr = ctx.Err()
58
-			}
59
-			wp.Unlock()
60
-		}
61
-	}()
62
-
63
-	return wp, nil
64
-}
65
-
66
-func (wp *winpipe) Read(b []byte) (int, error) {
67
-	select {
68
-	case <-wp.ctx.Done():
69
-		return 0, wp.ctx.Err()
70
-	case <-wp.readyCh:
71
-		return wp.client.Read(b)
72
-	}
73
-}
74
-
75
-func (wp *winpipe) Write(b []byte) (int, error) {
76
-	select {
77
-	case <-wp.ctx.Done():
78
-		return 0, wp.ctx.Err()
79
-	case <-wp.readyCh:
80
-		return wp.client.Write(b)
81
-	}
82
-}
83
-
84
-func (wp *winpipe) Close() error {
85
-	select {
86
-	case <-wp.readyCh:
87
-		return wp.client.Close()
88
-	default:
89
-		return nil
90
-	}
91
-}
92
-
93
-func newIOPipe(fifos *cio.FIFOSet) (*IOPipe, error) {
94
-	var (
95
-		err         error
96
-		ctx, cancel = context.WithCancel(context.Background())
97
-		p           io.ReadWriteCloser
98
-		iop         = &IOPipe{
99
-			Terminal: fifos.Terminal,
100
-			cancel:   cancel,
101
-			config: cio.Config{
102
-				Terminal: fifos.Terminal,
103
-				Stdin:    fifos.In,
104
-				Stdout:   fifos.Out,
105
-				Stderr:   fifos.Err,
106
-			},
107
-		}
108
-	)
109
-	defer func() {
110
-		if err != nil {
111
-			cancel()
112
-			iop.Close()
113
-		}
114
-	}()
115
-
116
-	if fifos.In != "" {
117
-		if p, err = newWinpipe(ctx, fifos.In); err != nil {
118
-			return nil, err
119
-		}
120
-		iop.Stdin = p
121
-	}
122
-
123
-	if fifos.Out != "" {
124
-		if p, err = newWinpipe(ctx, fifos.Out); err != nil {
125
-			return nil, err
126
-		}
127
-		iop.Stdout = p
128
-	}
129
-
130
-	if fifos.Err != "" {
131
-		if p, err = newWinpipe(ctx, fifos.Err); err != nil {
132
-			return nil, err
133
-		}
134
-		iop.Stderr = p
135
-	}
136
-
137
-	return iop, nil
138
-}
139 1
deleted file mode 100644
... ...
@@ -1,56 +0,0 @@
1
-// +build !windows
2
-
3
-package libcontainerd
4
-
5
-import "github.com/pkg/errors"
6
-
7
-// process represents the state for the main container process or an exec.
8
-type process struct {
9
-	// id is the logical name of the process
10
-	id string
11
-
12
-	// cid is the container id to which this process belongs
13
-	cid string
14
-
15
-	// pid is the identifier of the process
16
-	pid uint32
17
-
18
-	// io holds the io reader/writer associated with the process
19
-	io *IOPipe
20
-
21
-	// root is the state directory for the process
22
-	root string
23
-}
24
-
25
-func (p *process) ID() string {
26
-	return p.id
27
-}
28
-
29
-func (p *process) Pid() uint32 {
30
-	return p.pid
31
-}
32
-
33
-func (p *process) SetPid(pid uint32) error {
34
-	if p.pid != 0 {
35
-		return errors.Errorf("pid is already set to %d", pid)
36
-	}
37
-
38
-	p.pid = pid
39
-	return nil
40
-}
41
-
42
-func (p *process) IOPipe() *IOPipe {
43
-	return p.io
44
-}
45
-
46
-func (p *process) CloseIO() {
47
-	if p.io.Stdin != nil {
48
-		p.io.Stdin.Close()
49
-	}
50
-	if p.io.Stdout != nil {
51
-		p.io.Stdout.Close()
52
-	}
53
-	if p.io.Stderr != nil {
54
-		p.io.Stderr.Close()
55
-	}
56
-}
57 1
deleted file mode 100644
... ...
@@ -1,59 +0,0 @@
1
-package libcontainerd
2
-
3
-import (
4
-	"os"
5
-	"path/filepath"
6
-
7
-	"github.com/pkg/errors"
8
-	"golang.org/x/sys/unix"
9
-)
10
-
11
-var fdNames = map[int]string{
12
-	unix.Stdin:  "stdin",
13
-	unix.Stdout: "stdout",
14
-	unix.Stderr: "stderr",
15
-}
16
-
17
-func (p *process) pipeName(index int) string {
18
-	return filepath.Join(p.root, p.id+"-"+fdNames[index])
19
-}
20
-
21
-func (p *process) IOPaths() (string, string, string) {
22
-	var (
23
-		stdin  = p.pipeName(unix.Stdin)
24
-		stdout = p.pipeName(unix.Stdout)
25
-		stderr = p.pipeName(unix.Stderr)
26
-	)
27
-	// TODO: debug why we're having zombies when I don't unset those
28
-	if p.io.Stdin == nil {
29
-		stdin = ""
30
-	}
31
-	if p.io.Stderr == nil {
32
-		stderr = ""
33
-	}
34
-	return stdin, stdout, stderr
35
-}
36
-
37
-func (p *process) Cleanup() error {
38
-	var retErr error
39
-
40
-	// Ensure everything was closed
41
-	p.CloseIO()
42
-
43
-	for _, i := range [3]string{
44
-		p.pipeName(unix.Stdin),
45
-		p.pipeName(unix.Stdout),
46
-		p.pipeName(unix.Stderr),
47
-	} {
48
-		err := os.Remove(i)
49
-		if err != nil {
50
-			if retErr == nil {
51
-				retErr = errors.Wrapf(err, "failed to remove %s", i)
52
-			} else {
53
-				retErr = errors.Wrapf(retErr, "failed to remove %s", i)
54
-			}
55
-		}
56
-	}
57
-
58
-	return retErr
59
-}
... ...
@@ -2,7 +2,6 @@ package libcontainerd
2 2
 
3 3
 import (
4 4
 	"context"
5
-	"io"
6 5
 	"time"
7 6
 
8 7
 	"github.com/containerd/containerd"
... ...
@@ -107,20 +106,4 @@ type Client interface {
107 107
 }
108 108
 
109 109
 // StdioCallback is called to connect a container or process stdio.
110
-type StdioCallback func(*IOPipe) (cio.IO, error)
111
-
112
-// IOPipe contains the stdio streams.
113
-type IOPipe struct {
114
-	Stdin    io.WriteCloser
115
-	Stdout   io.ReadCloser
116
-	Stderr   io.ReadCloser
117
-	Terminal bool // Whether stderr is connected on Windows
118
-
119
-	cancel context.CancelFunc
120
-	config cio.Config
121
-}
122
-
123
-// ServerVersion contains version information as retrieved from the
124
-// server
125
-type ServerVersion struct {
126
-}
110
+type StdioCallback func(io *cio.DirectIO) (cio.IO, error)
... ...
@@ -122,7 +122,7 @@ func (c *rio) Wait() {
122 122
 }
123 123
 
124 124
 func attachStreamsFunc(stdout, stderr io.WriteCloser) libcontainerd.StdioCallback {
125
-	return func(iop *libcontainerd.IOPipe) (cio.IO, error) {
125
+	return func(iop *cio.DirectIO) (cio.IO, error) {
126 126
 		if iop.Stdin != nil {
127 127
 			iop.Stdin.Close()
128 128
 			// closing stdin shouldn't be needed here, it should never be open