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

10
tea.go
View File

@ -292,13 +292,7 @@ func (p *Program) StartReturningModel() (Model, error) {
waitForGoroutines = func(withReadLoop bool) {
if withReadLoop {
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.
}
p.waitForReadLoop()
}
<-cmdLoopDone
<-resizeLoopDone
@ -712,6 +706,8 @@ func (p *Program) DisableMouseAllMotion() {
func (p *Program) ReleaseTerminal() error {
p.ignoreSignals = true
p.cancelInput()
p.waitForReadLoop()
p.altScreenWasActive = p.altScreenActive
if p.altScreenActive {
p.ExitAltScreen()

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.
}
}