From ab182e276badc8222962f4d28a052dfa7f016d88 Mon Sep 17 00:00:00 2001 From: Tw Date: Wed, 24 May 2017 11:36:59 -0500 Subject: [PATCH] Use read syscall directly to get character (#931) Due to go std lib uses poller for os.File introducing in this commit: https://github.com/golang/go/commit/c05b06a12d005f50e4776095a60d6bd9c2c91fac There are two changes to watch out: 1. os.File.Fd will always return a blocking fd except on bsd. 2. os.File.Read won't return EAGAIN error for nonblocking fd. So For 1, we just get tty's fd in advance and then set its block mode. For 2, we use read syscall directly to get what we wanted error(EAGAIN). Fix issue #910. Signed-off-by: Tw --- src/tui/light.go | 3 ++- src/util/util_unix.go | 5 +++++ src/util/util_windows.go | 5 +++++ 3 files changed, 12 insertions(+), 1 deletion(-) diff --git a/src/tui/light.go b/src/tui/light.go index be6950c..e690ef9 100644 --- a/src/tui/light.go +++ b/src/tui/light.go @@ -251,8 +251,9 @@ func (r *LightRenderer) updateTerminalSize() { func (r *LightRenderer) getch(nonblock bool) (int, bool) { b := make([]byte, 1) + fd := r.fd() util.SetNonblock(r.ttyin, nonblock) - _, err := r.ttyin.Read(b) + _, err := util.Read(fd, b) if err != nil { return 0, false } diff --git a/src/util/util_unix.go b/src/util/util_unix.go index bc1b7b5..d538ee0 100644 --- a/src/util/util_unix.go +++ b/src/util/util_unix.go @@ -26,3 +26,8 @@ func IsWindows() bool { func SetNonblock(file *os.File, nonblock bool) { syscall.SetNonblock(int(file.Fd()), nonblock) } + +// Read executes syscall.Read on file descriptor +func Read(fd int, b []byte) (int, error) { + return syscall.Read(int(fd), b) +} diff --git a/src/util/util_windows.go b/src/util/util_windows.go index 9ba4f79..0664416 100644 --- a/src/util/util_windows.go +++ b/src/util/util_windows.go @@ -32,3 +32,8 @@ func IsWindows() bool { func SetNonblock(file *os.File, nonblock bool) { syscall.SetNonblock(syscall.Handle(file.Fd()), nonblock) } + +// Read executes syscall.Read on file descriptor +func Read(fd int, b []byte) (int, error) { + return syscall.Read(syscall.Handle(fd), b) +}