forked from Mirrors/bubbletea
fix: wait for read-loop to finish before spawning child process
This commit is contained in:
parent
93c63f07aa
commit
b1c9d80603
10
tea.go
10
tea.go
|
@ -292,13 +292,7 @@ func (p *Program) StartReturningModel() (Model, error) {
|
||||||
|
|
||||||
waitForGoroutines = func(withReadLoop bool) {
|
waitForGoroutines = func(withReadLoop bool) {
|
||||||
if withReadLoop {
|
if withReadLoop {
|
||||||
select {
|
p.waitForReadLoop()
|
||||||
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.
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
<-cmdLoopDone
|
<-cmdLoopDone
|
||||||
<-resizeLoopDone
|
<-resizeLoopDone
|
||||||
|
@ -712,6 +706,8 @@ func (p *Program) DisableMouseAllMotion() {
|
||||||
func (p *Program) ReleaseTerminal() error {
|
func (p *Program) ReleaseTerminal() error {
|
||||||
p.ignoreSignals = true
|
p.ignoreSignals = true
|
||||||
p.cancelInput()
|
p.cancelInput()
|
||||||
|
p.waitForReadLoop()
|
||||||
|
|
||||||
p.altScreenWasActive = p.altScreenActive
|
p.altScreenWasActive = p.altScreenActive
|
||||||
if p.altScreenActive {
|
if p.altScreenActive {
|
||||||
p.ExitAltScreen()
|
p.ExitAltScreen()
|
||||||
|
|
58
tty.go
58
tty.go
|
@ -3,6 +3,7 @@ package tea
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"io"
|
"io"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/muesli/cancelreader"
|
"github.com/muesli/cancelreader"
|
||||||
)
|
)
|
||||||
|
@ -48,33 +49,46 @@ func (p *Program) initCancelReader() error {
|
||||||
}
|
}
|
||||||
|
|
||||||
p.readLoopDone = make(chan struct{})
|
p.readLoopDone = make(chan struct{})
|
||||||
go func() {
|
go p.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
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
|
|
||||||
return nil
|
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.
|
// cancelInput cancels the input reader.
|
||||||
func (p *Program) cancelInput() {
|
func (p *Program) cancelInput() {
|
||||||
p.cancelReader.Cancel()
|
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.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue