From 6a673bf917a61cbd72b5ccb6c9e1f4cea39684f4 Mon Sep 17 00:00:00 2001 From: Cristian Maglie Date: Tue, 3 Dec 2019 20:26:03 +0100 Subject: [PATCH] Transparently handle EINTR during Read This has been observed in particular on MacOS, in this case just retry the call without throwing the error back to the user. Related to: https://github.com/arduino/arduino-cli/issues/504 https://github.com/arduino/arduino-pro-ide/issues/157 --- serial_unix.go | 27 ++++++++++++++++++--------- 1 file changed, 18 insertions(+), 9 deletions(-) diff --git a/serial_unix.go b/serial_unix.go index 6b8f8e9..8831fc2 100644 --- a/serial_unix.go +++ b/serial_unix.go @@ -15,8 +15,8 @@ import ( "sync" "unsafe" - "golang.org/x/sys/unix" "go.bug.st/serial/unixutils" + "golang.org/x/sys/unix" ) type unixPort struct { @@ -51,7 +51,7 @@ func (port *unixPort) Close() error { return nil } -func (port *unixPort) Read(p []byte) (n int, err error) { +func (port *unixPort) Read(p []byte) (int, error) { port.closeLock.RLock() defer port.closeLock.RUnlock() if !port.opened { @@ -59,14 +59,23 @@ func (port *unixPort) Read(p []byte) (n int, err error) { } fds := unixutils.NewFDSet(port.handle, port.closeSignal.ReadFD()) - res, err := unixutils.Select(fds, nil, fds, -1) - if err != nil { - return 0, err + for { + res, err := unixutils.Select(fds, nil, fds, -1) + if err == unix.EINTR { + continue + } + if err != nil { + return 0, err + } + if res.IsReadable(port.closeSignal.ReadFD()) { + return 0, &PortError{code: PortClosed} + } + n, err := unix.Read(port.handle, p) + if err == unix.EINTR { + continue + } + return n, err } - if res.IsReadable(port.closeSignal.ReadFD()) { - return 0, &PortError{code: PortClosed} - } - return unix.Read(port.handle, p) } func (port *unixPort) Write(p []byte) (n int, err error) {