handle race condition while setting raw mode in windows (#2509)

This commit is contained in:
Patrick Devine 2024-02-14 21:28:35 -08:00 committed by GitHub
parent 9241a29336
commit 42e77e2a69
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 38 additions and 15 deletions

View file

@ -32,6 +32,8 @@ func (p *Prompt) placeholder() string {
type Terminal struct {
outchan chan rune
rawmode bool
termios any
}
type Instance struct {
@ -60,6 +62,16 @@ func New(prompt Prompt) (*Instance, error) {
}
func (i *Instance) Readline() (string, error) {
if !i.Terminal.rawmode {
fd := int(syscall.Stdin)
termios, err := SetRawMode(fd)
if err != nil {
return "", err
}
i.Terminal.rawmode = true
i.Terminal.termios = termios
}
prompt := i.Prompt.prompt()
if i.Pasting {
// force alt prompt when pasting
@ -67,13 +79,12 @@ func (i *Instance) Readline() (string, error) {
}
fmt.Print(prompt)
defer func() {
fd := int(syscall.Stdin)
termios, err := SetRawMode(fd)
if err != nil {
return "", err
}
// nolint: errcheck
defer UnsetRawMode(fd, termios)
UnsetRawMode(fd, i.Terminal.termios)
i.Terminal.rawmode = false
}()
buf, _ := NewBuffer(i.Prompt)
@ -205,7 +216,8 @@ func (i *Instance) Readline() (string, error) {
case CharCtrlW:
buf.DeleteWord()
case CharCtrlZ:
return handleCharCtrlZ(fd, termios)
fd := int(syscall.Stdin)
return handleCharCtrlZ(fd, i.Terminal.termios)
case CharEnter:
output := buf.String()
if output != "" {
@ -236,8 +248,16 @@ func (i *Instance) HistoryDisable() {
}
func NewTerminal() (*Terminal, error) {
fd := int(syscall.Stdin)
termios, err := SetRawMode(fd)
if err != nil {
return nil, err
}
t := &Terminal{
outchan: make(chan rune),
rawmode: true,
termios: termios,
}
go t.ioloop()

View file

@ -6,8 +6,9 @@ import (
"syscall"
)
func handleCharCtrlZ(fd int, termios *Termios) (string, error) {
if err := UnsetRawMode(fd, termios); err != nil {
func handleCharCtrlZ(fd int, termios any) (string, error) {
t := termios.(*Termios)
if err := UnsetRawMode(fd, t); err != nil {
return "", err
}

View file

@ -1,6 +1,6 @@
package readline
func handleCharCtrlZ(fd int, state *State) (string, error) {
func handleCharCtrlZ(fd int, state any) (string, error) {
// not supported
return "", nil
}

View file

@ -25,8 +25,9 @@ func SetRawMode(fd int) (*Termios, error) {
return termios, setTermios(fd, &newTermios)
}
func UnsetRawMode(fd int, termios *Termios) error {
return setTermios(fd, termios)
func UnsetRawMode(fd int, termios any) error {
t := termios.(*Termios)
return setTermios(fd, t)
}
// IsTerminal returns true if the given file descriptor is a terminal.

View file

@ -56,7 +56,8 @@ func SetRawMode(fd int) (*State, error) {
return &State{st}, nil
}
func UnsetRawMode(fd int, state *State) error {
_, _, err := syscall.SyscallN(procSetConsoleMode.Addr(), uintptr(fd), uintptr(state.mode), 0)
func UnsetRawMode(fd int, state any) error {
s := state.(*State)
_, _, err := syscall.SyscallN(procSetConsoleMode.Addr(), uintptr(fd), uintptr(s.mode), 0)
return err
}