@@ -25,16 +25,24 @@ type Reader struct {
2525 event int32
2626 finChan chan bool
2727 mutex sync.Mutex
28- exec * exec.Cmd
29- execOut io.ReadCloser
28+ termFunc func ()
3029 command * string
31- killed bool
3230 wait bool
3331}
3432
3533// NewReader returns new Reader object
3634func NewReader (pusher func ([]byte ) bool , eventBox * util.EventBox , executor * util.Executor , delimNil bool , wait bool ) * Reader {
37- return & Reader {pusher , executor , eventBox , delimNil , int32 (EvtReady ), make (chan bool , 1 ), sync.Mutex {}, nil , nil , nil , false , wait }
35+ return & Reader {
36+ pusher ,
37+ executor ,
38+ eventBox ,
39+ delimNil ,
40+ int32 (EvtReady ),
41+ make (chan bool , 1 ),
42+ sync.Mutex {},
43+ func () { os .Stdin .Close () },
44+ nil ,
45+ wait }
3846}
3947
4048func (r * Reader ) startEventPoller () {
@@ -61,6 +69,10 @@ func (r *Reader) startEventPoller() {
6169 }()
6270}
6371
72+ func (r * Reader ) wasKilled () bool {
73+ return r .termFunc == nil
74+ }
75+
6476func (r * Reader ) fin (success bool ) {
6577 atomic .StoreInt32 (& r .event , int32 (EvtReadFin ))
6678 if r .wait {
@@ -69,7 +81,7 @@ func (r *Reader) fin(success bool) {
6981
7082 r .mutex .Lock ()
7183 ret := r .command
72- if success || r .killed {
84+ if success || r .wasKilled () {
7385 ret = nil
7486 }
7587 r .mutex .Unlock ()
@@ -79,22 +91,27 @@ func (r *Reader) fin(success bool) {
7991
8092func (r * Reader ) terminate () {
8193 r .mutex .Lock ()
82- r .killed = true
83- if r .exec != nil && r .exec .Process != nil {
84- r .execOut .Close ()
85- util .KillCommand (r .exec )
86- } else {
87- os .Stdin .Close ()
94+ if r .termFunc != nil {
95+ r .termFunc ()
96+ r .termFunc = nil
8897 }
8998 r .mutex .Unlock ()
9099}
91100
92101func (r * Reader ) restart (command commandSpec , environ []string ) {
93102 r .event = int32 (EvtReady )
94103 r .startEventPoller ()
95- success := r .readFromCommand (command .command , environ )
96- r .fin (success )
97- removeFiles (command .tempFiles )
104+
105+ r .mutex .Lock ()
106+ defer r .mutex .Unlock ()
107+
108+ if exec , execOut := r .startCommand (command .command , environ ); exec != nil {
109+ go func () {
110+ success := r .feedCommandOutput (exec , execOut )
111+ r .fin (success )
112+ removeFiles (command .tempFiles )
113+ }()
114+ }
98115}
99116
100117func (r * Reader ) readChannel (inputChan chan string ) bool {
@@ -249,7 +266,6 @@ func trimPath(path string) string {
249266}
250267
251268func (r * Reader ) readFiles (root string , opts walkerOpts , ignores []string ) bool {
252- r .killed = false
253269 conf := fastwalk.Config {
254270 Follow : opts .follow ,
255271 // Use forward slashes when running a Windows binary under WSL or MSYS
@@ -280,39 +296,47 @@ func (r *Reader) readFiles(root string, opts walkerOpts, ignores []string) bool
280296 }
281297 r .mutex .Lock ()
282298 defer r .mutex .Unlock ()
283- if r .killed {
299+ if r .wasKilled () {
284300 return context .Canceled
285301 }
286302 return nil
287303 }
288304 return fastwalk .Walk (& conf , root , fn ) == nil
289305}
290306
291- func ( r * Reader ) readFromCommand ( command string , environ [] string ) bool {
292- r . mutex . Lock ()
293- r .killed = false
307+ // Should be called with the mutex held
308+ func ( r * Reader ) startCommand ( command string , environ [] string ) ( * exec. Cmd , io. ReadCloser ) {
309+ r .termFunc = nil
294310 r .command = & command
295- r . exec = r .executor .ExecCommand (command , true )
311+ exec : = r .executor .ExecCommand (command , true )
296312 if environ != nil {
297- r . exec .Env = environ
313+ exec .Env = environ
298314 }
299-
300- var err error
301- r .execOut , err = r .exec .StdoutPipe ()
302- if err != nil {
303- r .exec = nil
304- r .mutex .Unlock ()
305- return false
315+ execOut , err := exec .StdoutPipe ()
316+ if err != nil || exec .Start () != nil {
317+ return nil , nil
306318 }
307319
308- err = r .exec .Start ()
309- if err != nil {
310- r .exec = nil
311- r .mutex .Unlock ()
312- return false
320+ // Function to call to terminate the running command
321+ r .termFunc = func () {
322+ execOut .Close ()
323+ util .KillCommand (exec )
313324 }
314325
326+ return exec , execOut
327+ }
328+
329+ func (r * Reader ) feedCommandOutput (exec * exec.Cmd , execOut io.ReadCloser ) bool {
330+ r .feed (execOut )
331+ return exec .Wait () == nil
332+ }
333+
334+ func (r * Reader ) readFromCommand (command string , environ []string ) bool {
335+ r .mutex .Lock ()
336+ exec , execOut := r .startCommand (command , environ )
315337 r .mutex .Unlock ()
316- r .feed (r .execOut )
317- return r .exec .Wait () == nil
338+ if exec == nil {
339+ return false
340+ }
341+ return r .feedCommandOutput (exec , execOut )
318342}
0 commit comments