@@ -24,6 +24,7 @@ import (
2424 "io"
2525 "os"
2626 "sync"
27+ "sync/atomic"
2728 "syscall"
2829
2930 "github.com/containerd/containerd/log"
@@ -39,7 +40,7 @@ var bufPool = sync.Pool{
3940}
4041
4142func copyPipes (ctx context.Context , rio runc.IO , stdin , stdout , stderr string , wg , cwg * sync.WaitGroup ) error {
42- var sameFile io. WriteCloser
43+ var sameFile * countingWriteCloser
4344 for _ , i := range []struct {
4445 name string
4546 dest func (wc io.WriteCloser , rc io.Closer )
@@ -101,14 +102,18 @@ func copyPipes(ctx context.Context, rio runc.IO, stdin, stdout, stderr string, w
101102 }
102103 } else {
103104 if sameFile != nil {
105+ sameFile .count ++
104106 i .dest (sameFile , nil )
105107 continue
106108 }
107109 if fw , err = os .OpenFile (i .name , syscall .O_WRONLY | syscall .O_APPEND , 0 ); err != nil {
108110 return fmt .Errorf ("containerd-shim: opening %s failed: %s" , i .name , err )
109111 }
110112 if stdout == stderr {
111- sameFile = fw
113+ sameFile = & countingWriteCloser {
114+ WriteCloser : fw ,
115+ count : 1 ,
116+ }
112117 }
113118 }
114119 i .dest (fw , fr )
@@ -134,6 +139,19 @@ func copyPipes(ctx context.Context, rio runc.IO, stdin, stdout, stderr string, w
134139 return nil
135140}
136141
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+
137155// isFifo checks if a file is a fifo
138156// if the file does not exist then it returns false
139157func isFifo (path string ) (bool , error ) {
0 commit comments