Skip to content

Commit

Permalink
fix: wait for read-loop to finish before spawning child process
Browse files Browse the repository at this point in the history
  • Loading branch information
muesli committed Sep 27, 2022
1 parent 93c63f0 commit 2484b42
Show file tree
Hide file tree
Showing 2 changed files with 34 additions and 24 deletions.
10 changes: 3 additions & 7 deletions tea.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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()
Expand Down
48 changes: 31 additions & 17 deletions tty.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package tea
import (
"errors"
"io"
"time"

"github.com/muesli/cancelreader"
)
Expand Down Expand Up @@ -48,33 +49,46 @@ func (p *Program) initCancelReader() error {
}

p.readLoopDone = make(chan struct{})
go func() {
defer close(p.readLoopDone)
go p.eventLoop()

for {
if p.ctx.Err() != nil {
return
}
return nil
}

msgs, err := readInputs(p.cancelReader)
if err != nil {
if !errors.Is(err, io.EOF) && !errors.Is(err, cancelreader.ErrCanceled) {
p.errs <- err
}
func (p *Program) eventLoop() {
defer close(p.readLoopDone)

return
}
for {
if p.ctx.Err() != nil {
return
}

for _, msg := range msgs {
p.msgs <- msg
msgs, err := readInputs(p.cancelReader)
if err != nil {
if !errors.Is(err, io.EOF) && !errors.Is(err, cancelreader.ErrCanceled) {
p.errs <- err
}

return
}
}()

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

0 comments on commit 2484b42

Please sign in to comment.