diff --git a/tools/utils/select_posix.go b/tools/utils/select_posix.go new file mode 100644 index 000000000..81a63f1cd --- /dev/null +++ b/tools/utils/select_posix.go @@ -0,0 +1,29 @@ +//go:build !darwin + +package utils + +import ( + "os" + "time" + + "golang.org/x/sys/unix" +) + +func Select(nfd int, r *unix.FdSet, w *unix.FdSet, e *unix.FdSet, timeout time.Duration) (n int, err error) { + deadline := time.Now().Add(timeout) + for { + t := deadline.Sub(time.Now()) + if t < 0 { + t = 0 + } + ts := NsecToTimespec(t) + q, qerr := unix.Pselect(nfd, r, w, w, &ts, nil) + if qerr == unix.EINTR { + if time.Now().After(deadline) { + return 0, os.ErrDeadlineExceeded + } + continue + } + return q, qerr + } +} diff --git a/tools/utils/select_without_pselect.go b/tools/utils/select_without_pselect.go new file mode 100644 index 000000000..053a8aef1 --- /dev/null +++ b/tools/utils/select_without_pselect.go @@ -0,0 +1,31 @@ +//go:build darwin + +package utils + +import ( + "os" + "time" + + "golang.org/x/sys/unix" +) + +// Go unix does not wrap pselect on darwin + +func Select(nfd int, r *unix.FdSet, w *unix.FdSet, e *unix.FdSet, timeout time.Duration) (n int, err error) { + deadline := time.Now().Add(timeout) + for { + t := deadline.Sub(time.Now()) + if t < 0 { + t = 0 + } + ts := NsecToTimeval(t) + q, qerr := unix.Select(nfd, r, w, w, &ts) + if qerr == unix.EINTR { + if time.Now().After(deadline) { + return 0, os.ErrDeadlineExceeded + } + continue + } + return q, qerr + } +}