Unverified Commit 42e77e2a authored by Patrick Devine's avatar Patrick Devine Committed by GitHub
Browse files

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

parent 9241a293
......@@ -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)
fd := int(syscall.Stdin)
termios, err := SetRawMode(fd)
if err != nil {
return "", err
}
// nolint: errcheck
defer UnsetRawMode(fd, termios)
defer func() {
fd := int(syscall.Stdin)
// nolint: errcheck
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()
......
......@@ -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
}
......
package readline
func handleCharCtrlZ(fd int, state *State) (string, error) {
func handleCharCtrlZ(fd int, state any) (string, error) {
// not supported
return "", nil
}
......@@ -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.
......
......@@ -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
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment