Skip to content

Commit d8f2159

Browse files
committed
fix: fix race conditions
1 parent 981a3ca commit d8f2159

File tree

2 files changed

+31
-0
lines changed

2 files changed

+31
-0
lines changed

prompt.go

+16
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import (
44
"fmt"
55
"io"
66
"strings"
7+
"sync"
78
"text/template"
89

910
"github.com/chzyer/readline"
@@ -113,6 +114,9 @@ type PromptTemplates struct {
113114
// Run will keep the prompt alive until it has been canceled from the command prompt or it has received a valid
114115
// value. It will return the value and an error if any occurred during the prompt's execution.
115116
func (p *Prompt) Run() (string, error) {
117+
mutex := new(sync.Mutex)
118+
closing := false
119+
116120
var err error
117121

118122
err = p.prepareTemplates()
@@ -159,6 +163,13 @@ func (p *Prompt) Run() (string, error) {
159163
cur := NewCursor(input, p.Pointer, eraseDefault)
160164

161165
listen := func(input []rune, pos int, key rune) ([]rune, int, bool) {
166+
mutex.Lock()
167+
defer mutex.Unlock()
168+
169+
if closing {
170+
return nil, 0, false
171+
}
172+
162173
_, _, keepOn := cur.Listen(input, pos, key)
163174
err := validFn(cur.Get())
164175
var prompt []byte
@@ -193,6 +204,7 @@ func (p *Prompt) Run() (string, error) {
193204

194205
for {
195206
_, err = rl.Readline()
207+
mutex.Lock()
196208
inputErr = validFn(cur.Get())
197209
if inputErr == nil {
198210
break
@@ -201,8 +213,12 @@ func (p *Prompt) Run() (string, error) {
201213
if err != nil {
202214
break
203215
}
216+
mutex.Unlock()
204217
}
205218

219+
defer mutex.Unlock()
220+
closing = true
221+
206222
if err != nil {
207223
switch err {
208224
case readline.ErrInterrupt:

select.go

+15
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import (
55
"fmt"
66
"io"
77
"os"
8+
"sync"
89
"text/template"
910

1011
"github.com/chzyer/readline"
@@ -220,6 +221,9 @@ func (s *Select) RunCursorAt(cursorPos, scroll int) (int, string, error) {
220221
}
221222

222223
func (s *Select) innerRun(cursorPos, scroll int, top rune) (int, string, error) {
224+
mutex := new(sync.Mutex)
225+
closing := false
226+
223227
c := &readline.Config{
224228
Stdin: s.Stdin,
225229
Stdout: s.Stdout,
@@ -254,6 +258,13 @@ func (s *Select) innerRun(cursorPos, scroll int, top rune) (int, string, error)
254258
s.list.SetStart(scroll)
255259

256260
c.SetListener(func(line []rune, pos int, key rune) ([]rune, int, bool) {
261+
mutex.Lock()
262+
defer mutex.Unlock()
263+
264+
if closing {
265+
return nil, 0, false
266+
}
267+
257268
switch {
258269
case key == KeyEnter:
259270
return nil, 0, true
@@ -373,6 +384,10 @@ func (s *Select) innerRun(cursorPos, scroll int, top rune) (int, string, error)
373384

374385
}
375386

387+
mutex.Lock()
388+
defer mutex.Unlock()
389+
closing = true
390+
376391
if err != nil {
377392
if err.Error() == "Interrupt" {
378393
err = ErrInterrupt

0 commit comments

Comments
 (0)