@@ -24,8 +24,10 @@ import (
2424 "io"
2525 "os"
2626 "sync"
27+ "sync/atomic"
2728 "syscall"
2829
30+ "github.com/containerd/containerd/log"
2931 "github.com/containerd/fifo"
3032 runc "github.com/containerd/go-runc"
3133)
@@ -38,7 +40,7 @@ var bufPool = sync.Pool{
3840}
3941
4042func copyPipes (ctx context.Context , rio runc.IO , stdin , stdout , stderr string , wg , cwg * sync.WaitGroup ) error {
41- var sameFile io. WriteCloser
43+ var sameFile * countingWriteCloser
4244 for _ , i := range []struct {
4345 name string
4446 dest func (wc io.WriteCloser , rc io.Closer )
@@ -52,7 +54,9 @@ func copyPipes(ctx context.Context, rio runc.IO, stdin, stdout, stderr string, w
5254 cwg .Done ()
5355 p := bufPool .Get ().(* []byte )
5456 defer bufPool .Put (p )
55- io .CopyBuffer (wc , rio .Stdout (), * p )
57+ if _ , err := io .CopyBuffer (wc , rio .Stdout (), * p ); err != nil {
58+ log .G (ctx ).Warn ("error copying stdout" )
59+ }
5660 wg .Done ()
5761 wc .Close ()
5862 if rc != nil {
@@ -69,7 +73,9 @@ func copyPipes(ctx context.Context, rio runc.IO, stdin, stdout, stderr string, w
6973 cwg .Done ()
7074 p := bufPool .Get ().(* []byte )
7175 defer bufPool .Put (p )
72- io .CopyBuffer (wc , rio .Stderr (), * p )
76+ if _ , err := io .CopyBuffer (wc , rio .Stderr (), * p ); err != nil {
77+ log .G (ctx ).Warn ("error copying stderr" )
78+ }
7379 wg .Done ()
7480 wc .Close ()
7581 if rc != nil {
@@ -96,14 +102,18 @@ func copyPipes(ctx context.Context, rio runc.IO, stdin, stdout, stderr string, w
96102 }
97103 } else {
98104 if sameFile != nil {
105+ sameFile .count ++
99106 i .dest (sameFile , nil )
100107 continue
101108 }
102109 if fw , err = os .OpenFile (i .name , syscall .O_WRONLY | syscall .O_APPEND , 0 ); err != nil {
103110 return fmt .Errorf ("containerd-shim: opening %s failed: %s" , i .name , err )
104111 }
105112 if stdout == stderr {
106- sameFile = fw
113+ sameFile = & countingWriteCloser {
114+ WriteCloser : fw ,
115+ count : 1 ,
116+ }
107117 }
108118 }
109119 i .dest (fw , fr )
@@ -129,6 +139,19 @@ func copyPipes(ctx context.Context, rio runc.IO, stdin, stdout, stderr string, w
129139 return nil
130140}
131141
142+ // countingWriteCloser masks io.Closer() until close has been invoked a certain number of times.
143+ type countingWriteCloser struct {
144+ io.WriteCloser
145+ count int64
146+ }
147+
148+ func (c * countingWriteCloser ) Close () error {
149+ if atomic .AddInt64 (& c .count , - 1 ) > 0 {
150+ return nil
151+ }
152+ return c .WriteCloser .Close ()
153+ }
154+
132155// isFifo checks if a file is a fifo
133156// if the file does not exist then it returns false
134157func isFifo (path string ) (bool , error ) {
0 commit comments