@@ -67,20 +67,23 @@ type IOConnectorPair struct {
67
67
}
68
68
69
69
func (connectorPair * IOConnectorPair ) proxy (
70
- proc * vmProc ,
70
+ ctx context. Context ,
71
71
logger * logrus.Entry ,
72
72
timeoutAfterExit time.Duration ,
73
73
) (ioInitDone <- chan error , ioCopyDone <- chan error ) {
74
74
initDone := make (chan error , 2 )
75
75
copyDone := make (chan error )
76
76
77
+ ioCtx , ioCancel := context .WithCancel (context .Background ())
78
+
77
79
// Start the initialization process. Any synchronous setup made by the connectors will
78
80
// be completed after these lines. Async setup will be done once initDone is closed in
79
81
// the goroutine below.
80
- readerResultCh := connectorPair .ReadConnector (proc . ctx , logger .WithField ("direction" , "read" ))
81
- writerResultCh := connectorPair .WriteConnector (proc . ctx , logger .WithField ("direction" , "write" ))
82
+ readerResultCh := connectorPair .ReadConnector (ioCtx , logger .WithField ("direction" , "read" ))
83
+ writerResultCh := connectorPair .WriteConnector (ioCtx , logger .WithField ("direction" , "write" ))
82
84
83
85
go func () {
86
+ defer ioCancel ()
84
87
defer close (copyDone )
85
88
86
89
var reader io.ReadCloser
@@ -119,7 +122,7 @@ func (connectorPair *IOConnectorPair) proxy(
119
122
// If the io streams close on their own before the timeout, the Close calls here
120
123
// should just be no-ops.
121
124
go func () {
122
- <- proc . ctx .Done ()
125
+ <- ctx .Done ()
123
126
time .AfterFunc (timeoutAfterExit , func () {
124
127
logClose (logger , reader , writer )
125
128
})
@@ -129,6 +132,7 @@ func (connectorPair *IOConnectorPair) proxy(
129
132
defer logger .Debug ("end copying io" )
130
133
131
134
size , err := io .CopyBuffer (writer , reader , make ([]byte , internal .DefaultBufferSize ))
135
+ logger .Debugf ("copied %d" , size )
132
136
if err != nil {
133
137
if strings .Contains (err .Error (), "use of closed network connection" ) ||
134
138
strings .Contains (err .Error (), "file already closed" ) {
@@ -138,7 +142,6 @@ func (connectorPair *IOConnectorPair) proxy(
138
142
}
139
143
copyDone <- err
140
144
}
141
- logger .Debugf ("copied %d" , size )
142
145
defer logClose (logger , reader , writer )
143
146
}()
144
147
@@ -174,19 +177,20 @@ func (ioConnectorSet *ioConnectorSet) start(proc *vmProc) (ioInitDone <-chan err
174
177
if ioConnectorSet .stdin != nil {
175
178
// For Stdin only, provide 0 as the timeout to wait after the proc exits before closing IO streams.
176
179
// There's no reason to send stdin data to a proc that's already dead.
177
- waitErrs (ioConnectorSet .stdin .proxy (proc , proc .logger .WithField ("stream" , "stdin" ), 0 ))
180
+ waitErrs (ioConnectorSet .stdin .proxy (proc .ctx , proc .logger .WithField ("stream" , "stdin" ), 0 ))
181
+
178
182
} else {
179
183
proc .logger .Debug ("skipping proxy io for unset stdin" )
180
184
}
181
185
182
186
if ioConnectorSet .stdout != nil {
183
- waitErrs (ioConnectorSet .stdout .proxy (proc , proc .logger .WithField ("stream" , "stdout" ), defaultIOFlushTimeout ))
187
+ waitErrs (ioConnectorSet .stdout .proxy (proc . ctx , proc .logger .WithField ("stream" , "stdout" ), defaultIOFlushTimeout ))
184
188
} else {
185
189
proc .logger .Debug ("skipping proxy io for unset stdout" )
186
190
}
187
191
188
192
if ioConnectorSet .stderr != nil {
189
- waitErrs (ioConnectorSet .stderr .proxy (proc , proc .logger .WithField ("stream" , "stderr" ), defaultIOFlushTimeout ))
193
+ waitErrs (ioConnectorSet .stderr .proxy (proc . ctx , proc .logger .WithField ("stream" , "stderr" ), defaultIOFlushTimeout ))
190
194
} else {
191
195
proc .logger .Debug ("skipping proxy io for unset stderr" )
192
196
}
0 commit comments