fix: race changing ignoreSignals (#791)

* fix: race changing ignoreSignals

* fix: atomic.Uint32
This commit is contained in:
Carlos Alexandro Becker 2023-11-07 13:49:00 -03:00 committed by GitHub
parent 5536bca34e
commit 5984e69f09
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 9 additions and 6 deletions

View File

@ -3,6 +3,7 @@ package tea
import (
"context"
"io"
"sync/atomic"
"github.com/muesli/termenv"
)
@ -76,7 +77,7 @@ func WithoutCatchPanics() ProgramOption {
// This is mainly useful for testing.
func WithoutSignals() ProgramOption {
return func(p *Program) {
p.ignoreSignals = true
atomic.StoreUint32(&p.ignoreSignals, 1)
}
}

View File

@ -2,6 +2,7 @@ package tea
import (
"bytes"
"sync/atomic"
"testing"
)
@ -37,7 +38,7 @@ func TestOptions(t *testing.T) {
t.Run("without signals", func(t *testing.T) {
p := NewProgram(nil, WithoutSignals())
if !p.ignoreSignals {
if atomic.LoadUint32(&p.ignoreSignals) == 0 {
t.Errorf("ignore signals should have been set")
}
})

9
tea.go
View File

@ -18,6 +18,7 @@ import (
"os/signal"
"runtime/debug"
"sync"
"sync/atomic"
"syscall"
"github.com/containerd/console"
@ -153,7 +154,7 @@ type Program struct {
// was the altscreen active before releasing the terminal?
altScreenWasActive bool
ignoreSignals bool
ignoreSignals uint32
// Stores the original reference to stdin for cases where input is not a
// TTY on windows and we've automatically opened CONIN$ to receive input.
@ -238,7 +239,7 @@ func (p *Program) handleSignals() chan struct{} {
return
case <-sig:
if !p.ignoreSignals {
if atomic.LoadUint32(&p.ignoreSignals) == 0 {
p.msgs <- QuitMsg{}
return
}
@ -632,7 +633,7 @@ func (p *Program) shutdown(kill bool) {
// ReleaseTerminal restores the original terminal state and cancels the input
// reader. You can return control to the Program with RestoreTerminal.
func (p *Program) ReleaseTerminal() error {
p.ignoreSignals = true
atomic.StoreUint32(&p.ignoreSignals, 1)
p.cancelReader.Cancel()
p.waitForReadLoop()
@ -648,7 +649,7 @@ func (p *Program) ReleaseTerminal() error {
// terminal to the former state when the program was running, and repaints.
// Use it to reinitialize a Program after running ReleaseTerminal.
func (p *Program) RestoreTerminal() error {
p.ignoreSignals = false
atomic.StoreUint32(&p.ignoreSignals, 0)
if err := p.initTerminal(); err != nil {
return err