mirror of
https://github.com/junegunn/fzf.git
synced 2026-09-19 02:03:19 +08:00
Fix spurious exit while waiting for a key with --listen
- getch() charged EINTR against a 100 iteration limit meant for read
attempts, and the count only reset once a byte was read
- So signals arriving during an idle prompt drained it, and running out
returned getCharError, which became Event{Fatal} and exit status 2
- Only the cancellable path is affected, hence only --listen
- select() is not restarted by SA_RESTART, unlike the blocking read on
the non-cancellable path, so it is the only one that sees EINTR
- waitReadable() already retries EINTR without a limit
Fix #4917
This commit is contained in:
@@ -27,7 +27,6 @@ const (
|
|||||||
queryTimeout = 500 * time.Millisecond
|
queryTimeout = 500 * time.Millisecond
|
||||||
maxInputBuffer = 1024 * 1024
|
maxInputBuffer = 1024 * 1024
|
||||||
escapeLookback = 256
|
escapeLookback = 256
|
||||||
maxSelectTries = 100
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const DefaultTtyDevice string = "/dev/tty"
|
const DefaultTtyDevice string = "/dev/tty"
|
||||||
|
|||||||
@@ -240,7 +240,7 @@ func (r *LightRenderer) getch(cancellable bool, nonblock bool) (int, getCharResu
|
|||||||
}()
|
}()
|
||||||
|
|
||||||
cancelFd := int(rpipe.Fd())
|
cancelFd := int(rpipe.Fd())
|
||||||
for range maxSelectTries {
|
for {
|
||||||
var rfds unix.FdSet
|
var rfds unix.FdSet
|
||||||
limit := len(rfds.Bits) * unix.NFDBITS
|
limit := len(rfds.Bits) * unix.NFDBITS
|
||||||
if fd >= limit || cancelFd >= limit {
|
if fd >= limit || cancelFd >= limit {
|
||||||
@@ -251,6 +251,8 @@ func (r *LightRenderer) getch(cancellable bool, nonblock bool) (int, getCharResu
|
|||||||
rfds.Set(cancelFd)
|
rfds.Set(cancelFd)
|
||||||
_, err := unix.Select(max(fd, cancelFd)+1, &rfds, nil, nil, nil)
|
_, err := unix.Select(max(fd, cancelFd)+1, &rfds, nil, nil, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
// An interrupted wait is not a failed read, so it must not count
|
||||||
|
// against anything. Retry until the fd is ready or the wait fails.
|
||||||
if err == syscall.EINTR {
|
if err == syscall.EINTR {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
@@ -265,7 +267,6 @@ func (r *LightRenderer) getch(cancellable bool, nonblock bool) (int, getCharResu
|
|||||||
return getter()
|
return getter()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return 0, getCharError
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *LightRenderer) Size() TermSize {
|
func (r *LightRenderer) Size() TermSize {
|
||||||
|
|||||||
Reference in New Issue
Block a user