From 2210a0e9ade26dbcfb5e318de9a8ce45c9016bef Mon Sep 17 00:00:00 2001 From: Quentin McGaw Date: Thu, 21 May 2026 15:44:21 +0000 Subject: [PATCH] fix(command): fix rare race condition on log line stream at command completion --- internal/command/start.go | 27 +++++++++------------------ 1 file changed, 9 insertions(+), 18 deletions(-) diff --git a/internal/command/start.go b/internal/command/start.go index 523b7073..b2405cde 100644 --- a/internal/command/start.go +++ b/internal/command/start.go @@ -21,7 +21,6 @@ func (c *Cmder) Start(cmd *exec.Cmd) ( func start(cmd execCmd) (stdoutLines, stderrLines <-chan string, waitError <-chan error, startErr error, ) { - stop := make(chan struct{}) stdoutReady := make(chan struct{}) stdoutLinesCh := make(chan string) stdoutDone := make(chan struct{}) @@ -33,22 +32,20 @@ func start(cmd execCmd) (stdoutLines, stderrLines <-chan string, if err != nil { return nil, nil, nil, err } - go streamToChannel(stdoutReady, stop, stdoutDone, stdout, stdoutLinesCh) + go streamToChannel(stdoutReady, stdoutDone, stdout, stdoutLinesCh) stderr, err := cmd.StderrPipe() if err != nil { _ = stdout.Close() - close(stop) <-stdoutDone return nil, nil, nil, err } - go streamToChannel(stderrReady, stop, stderrDone, stderr, stderrLinesCh) + go streamToChannel(stderrReady, stderrDone, stderr, stderrLinesCh) err = cmd.Start() if err != nil { _ = stdout.Close() _ = stderr.Close() - close(stop) <-stdoutDone <-stderrDone return nil, nil, nil, err @@ -57,19 +54,20 @@ func start(cmd execCmd) (stdoutLines, stderrLines <-chan string, waitErrorCh := make(chan error) go func() { err := cmd.Wait() - _ = stdout.Close() - _ = stderr.Close() - close(stop) <-stdoutDone <-stderrDone + _ = stdout.Close() + _ = stderr.Close() waitErrorCh <- err }() + <-stdoutReady + <-stderrReady + return stdoutLinesCh, stderrLinesCh, waitErrorCh, nil } -func streamToChannel(ready chan<- struct{}, - stop <-chan struct{}, done chan<- struct{}, +func streamToChannel(ready chan<- struct{}, done chan<- struct{}, stream io.Reader, lines chan<- string, ) { defer close(done) @@ -89,12 +87,5 @@ func streamToChannel(ready chan<- struct{}, if err == nil || errors.Is(err, os.ErrClosed) { return } - - // ignore the error if it is stopped. - select { - case <-stop: - return - default: - lines <- "stream error: " + err.Error() - } + lines <- "stream error: " + err.Error() }