fix(command): fix rare race condition on log line stream at command completion

This commit is contained in:
Quentin McGaw
2026-05-21 15:44:21 +00:00
parent f8a677a424
commit 2210a0e9ad
+9 -18
View File
@@ -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()
}