Skip to content

Commit 71cab65

Browse files
cmaglieumbynos
andauthored
[skip-changelog] Proper handling of stdout/stderr copy in subprocess in integration tests (arduino#1862)
* Proper handling of stdout/stderr copy in subprocess * Apply suggestions from code review Co-authored-by: Umberto Baldi <[email protected]> Co-authored-by: Umberto Baldi <[email protected]>
1 parent 67a62d9 commit 71cab65

File tree

2 files changed

+21
-8
lines changed

2 files changed

+21
-8
lines changed

Diff for: executils/process.go

+10
Original file line numberDiff line numberDiff line change
@@ -86,12 +86,22 @@ func (p *Process) StdinPipe() (io.WriteCloser, error) {
8686

8787
// StdoutPipe returns a pipe that will be connected to the command's standard
8888
// output when the command starts.
89+
//
90+
// Wait will close the pipe after seeing the command exit, so most callers
91+
// don't need to close the pipe themselves. It is thus incorrect to call Wait
92+
// before all reads from the pipe have completed.
93+
// For the same reason, it is incorrect to call Run when using StdoutPipe.
8994
func (p *Process) StdoutPipe() (io.ReadCloser, error) {
9095
return p.cmd.StdoutPipe()
9196
}
9297

9398
// StderrPipe returns a pipe that will be connected to the command's standard
9499
// error when the command starts.
100+
//
101+
// Wait will close the pipe after seeing the command exit, so most callers
102+
// don't need to close the pipe themselves. It is thus incorrect to call Wait
103+
// before all reads from the pipe have completed.
104+
// For the same reason, it is incorrect to use Run when using StderrPipe.
95105
func (p *Process) StderrPipe() (io.ReadCloser, error) {
96106
return p.cmd.StderrPipe()
97107
}

Diff for: internal/integrationtest/arduino-cli.go

+11-8
Original file line numberDiff line numberDiff line change
@@ -143,19 +143,22 @@ func (cli *ArduinoCLI) Run(args ...string) ([]byte, []byte, error) {
143143
cli.t.NoError(cliProc.Start())
144144

145145
var stdoutBuf, stderrBuf bytes.Buffer
146-
stdoutCtx, stdoutCancel := context.WithCancel(context.Background())
147-
stderrCtx, stderrCancel := context.WithCancel(context.Background())
146+
var wg sync.WaitGroup
147+
wg.Add(2)
148148
go func() {
149-
io.Copy(&stdoutBuf, io.TeeReader(stdout, os.Stdout))
150-
stdoutCancel()
149+
defer wg.Done()
150+
if _, err := io.Copy(&stdoutBuf, io.TeeReader(stdout, os.Stdout)); err != nil {
151+
fmt.Println(color.HiBlackString("<<< stdout copy error:"), err)
152+
}
151153
}()
152154
go func() {
153-
io.Copy(&stderrBuf, io.TeeReader(stderr, os.Stderr))
154-
stderrCancel()
155+
defer wg.Done()
156+
if _, err := io.Copy(&stderrBuf, io.TeeReader(stderr, os.Stderr)); err != nil {
157+
fmt.Println(color.HiBlackString("<<< stderr copy error:"), err)
158+
}
155159
}()
160+
wg.Wait()
156161
cliErr := cliProc.Wait()
157-
<-stdoutCtx.Done()
158-
<-stderrCtx.Done()
159162
fmt.Println(color.HiBlackString("<<< Run completed (err = %v)", cliErr))
160163

161164
return stdoutBuf.Bytes(), stderrBuf.Bytes(), cliErr

0 commit comments

Comments
 (0)