fix: wait for read-loop to finish before spawning child process

This commit is contained in:
Christian Muehlhaeuser
2022-09-27 09:01:29 +02:00
parent 93c63f07aa
commit b1c9d80603
2 changed files with 39 additions and 29 deletions

58
tty.go
View File

@@ -3,6 +3,7 @@ package tea
import (
"errors"
"io"
"time"
"github.com/muesli/cancelreader"
)
@@ -48,33 +49,46 @@ func (p *Program) initCancelReader() error {
}
p.readLoopDone = make(chan struct{})
go func() {
defer close(p.readLoopDone)
for {
if p.ctx.Err() != nil {
return
}
msgs, err := readInputs(p.cancelReader)
if err != nil {
if !errors.Is(err, io.EOF) && !errors.Is(err, cancelreader.ErrCanceled) {
p.errs <- err
}
return
}
for _, msg := range msgs {
p.msgs <- msg
}
}
}()
go p.eventLoop()
return nil
}
func (p *Program) eventLoop() {
defer close(p.readLoopDone)
for {
if p.ctx.Err() != nil {
return
}
msgs, err := readInputs(p.cancelReader)
if err != nil {
if !errors.Is(err, io.EOF) && !errors.Is(err, cancelreader.ErrCanceled) {
p.errs <- err
}
return
}
for _, msg := range msgs {
p.msgs <- msg
}
}
}
// cancelInput cancels the input reader.
func (p *Program) cancelInput() {
p.cancelReader.Cancel()
}
// waitForReadLoop waits for the cancelReader to finish its read loop.
func (p *Program) waitForReadLoop() {
select {
case <-p.readLoopDone:
case <-time.After(500 * time.Millisecond):
// The read loop hangs, which means the input
// cancelReader's cancel function has returned true even
// though it was not able to cancel the read.
}
}