Skip to content

Commit

Permalink
read/read timeout: read again if the underlaying system call has been…
Browse files Browse the repository at this point in the history
… interrupted by a signal

some backgroud:
go1.14 introduced preemtible goroutines on some arches. therefor check
against interruption by a signal and do the read again.
this should not afect other platforms
  • Loading branch information
bearsh committed Dec 18, 2023
1 parent 7cb069c commit d869d37
Showing 1 changed file with 17 additions and 4 deletions.
21 changes: 17 additions & 4 deletions hid_enabled.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ import (
"errors"
"runtime"
"sync"
"syscall"
"unsafe"
)

Expand Down Expand Up @@ -316,9 +317,15 @@ func (dev *Device) Read(b []byte) (int, error) {
if device == nil {
return 0, ErrDeviceClosed
}

readAgain:
// Execute the read operation
read := int(C.hid_read(device, (*C.uchar)(&b[0]), C.size_t(len(b))))
read, err := C.hid_read(device, (*C.uchar)(&b[0]), C.size_t(len(b)))
if read == -1 {
if errno, ok := err.(syscall.Errno); ok && errno == syscall.EINTR {
goto readAgain
}

// If the read failed, verify if closed or other error
dev.lock.Lock()
device = dev.device
Expand All @@ -335,7 +342,7 @@ func (dev *Device) Read(b []byte) (int, error) {
failure, _ := wcharTToString(message)
return 0, errors.New("hidapi: " + failure)
}
return read, nil
return int(read), nil
}

// ReadTimeout retrieves an input report from a HID device with a timeout. If timeout is -1 a
Expand All @@ -357,9 +364,15 @@ func (dev *Device) ReadTimeout(b []byte, timeout int) (int, error) {
if device == nil {
return 0, ErrDeviceClosed
}

readAgain:
// Execute the read operation
read := int(C.hid_read_timeout(device, (*C.uchar)(&b[0]), C.size_t(len(b)), C.int(timeout)))
read, err := C.hid_read_timeout(device, (*C.uchar)(&b[0]), C.size_t(len(b)), C.int(timeout))
if read == -1 {
if errno, ok := err.(syscall.Errno); ok && errno == syscall.EINTR {
goto readAgain
}

// If the read failed, verify if closed or other error
dev.lock.Lock()
device = dev.device
Expand All @@ -376,7 +389,7 @@ func (dev *Device) ReadTimeout(b []byte, timeout int) (int, error) {
failure, _ := wcharTToString(message)
return 0, errors.New("hidapi: " + failure)
}
return read, nil
return int(read), nil
}

// GetFeatureReport retrieves a feature report from a HID device
Expand Down

0 comments on commit d869d37

Please sign in to comment.