@@ -27,6 +27,7 @@ import (
2727 "os/exec"
2828 "path/filepath"
2929 "sync"
30+ "sync/atomic"
3031 "syscall"
3132
3233 "github.com/containerd/containerd/log"
@@ -123,7 +124,7 @@ func createIO(ctx context.Context, id string, ioUID, ioGID int, stdio proc.Stdio
123124}
124125
125126func copyPipes (ctx context.Context , rio runc.IO , stdin , stdout , stderr string , wg , cwg * sync.WaitGroup ) error {
126- var sameFile io. WriteCloser
127+ var sameFile * countingWriteCloser
127128 for _ , i := range []struct {
128129 name string
129130 dest func (wc io.WriteCloser , rc io.Closer )
@@ -185,14 +186,18 @@ func copyPipes(ctx context.Context, rio runc.IO, stdin, stdout, stderr string, w
185186 }
186187 } else {
187188 if sameFile != nil {
189+ sameFile .count ++
188190 i .dest (sameFile , nil )
189191 continue
190192 }
191193 if fw , err = os .OpenFile (i .name , syscall .O_WRONLY | syscall .O_APPEND , 0 ); err != nil {
192194 return fmt .Errorf ("containerd-shim: opening %s failed: %s" , i .name , err )
193195 }
194196 if stdout == stderr {
195- sameFile = fw
197+ sameFile = & countingWriteCloser {
198+ WriteCloser : fw ,
199+ count : 1 ,
200+ }
196201 }
197202 }
198203 i .dest (fw , fr )
@@ -217,6 +222,19 @@ func copyPipes(ctx context.Context, rio runc.IO, stdin, stdout, stderr string, w
217222 return nil
218223}
219224
225+ // countingWriteCloser masks io.Closer() until close has been invoked a certain number of times.
226+ type countingWriteCloser struct {
227+ io.WriteCloser
228+ count int64
229+ }
230+
231+ func (c * countingWriteCloser ) Close () error {
232+ if atomic .AddInt64 (& c .count , - 1 ) > 0 {
233+ return nil
234+ }
235+ return c .WriteCloser .Close ()
236+ }
237+
220238// isFifo checks if a file is a fifo
221239// if the file does not exist then it returns false
222240func isFifo (path string ) (bool , error ) {
0 commit comments