unix: deflake TestPselect and TestSelect on linux

On some platforms (namely Linux), Select and Pselect update the
passed-in timeval/timespec, which might lead to failing tests in
case of an EINTR. Fix this by always resetting the timeval/timespec
before calling Select/Pselect.

Also change accept timeouts within 2/3 margin of the expected timeout,
like already done in TestSelect. While at it, fix the failure log to use
the common "got X, expected Y" message.

Fixes golang/go#42210

Change-Id: Id0efbbecc9c0bf44c102d5d1880b1bae32980ad1
Reviewed-on: https://go-review.googlesource.com/c/sys/+/265020
Trust: Tobias Klauser <tobias.klauser@gmail.com>
Run-TryBot: Tobias Klauser <tobias.klauser@gmail.com>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Bryan C. Mills <bcmills@google.com>
diff --git a/unix/syscall_linux_test.go b/unix/syscall_linux_test.go
index 76555d4..3625f46 100644
--- a/unix/syscall_linux_test.go
+++ b/unix/syscall_linux_test.go
@@ -234,9 +234,12 @@
 	}
 
 	dur := 2500 * time.Microsecond
-	ts := unix.NsecToTimespec(int64(dur))
 	var took time.Duration
 	for {
+		// On some platforms (e.g. Linux), the passed-in timespec is
+		// updated by pselect(2). Make sure to reset to the full
+		// duration in case of an EINTR.
+		ts := unix.NsecToTimespec(int64(dur))
 		start := time.Now()
 		n, err := unix.Pselect(0, nil, nil, nil, &ts, nil)
 		took = time.Since(start)
@@ -252,8 +255,10 @@
 		break
 	}
 
-	if took < dur {
-		t.Errorf("Pselect: timeout should have been at least %v, got %v", dur, took)
+	// On some builder the actual timeout might also be slightly less than the requested.
+	// Add an acceptable margin to avoid flaky tests.
+	if took < dur*2/3 {
+		t.Errorf("Pselect: got %v timeout, expected at least %v", took, dur)
 	}
 }
 
diff --git a/unix/syscall_unix_test.go b/unix/syscall_unix_test.go
index bebc169..473e790 100644
--- a/unix/syscall_unix_test.go
+++ b/unix/syscall_unix_test.go
@@ -537,9 +537,12 @@
 	}
 
 	dur := 250 * time.Millisecond
-	tv := unix.NsecToTimeval(int64(dur))
 	var took time.Duration
 	for {
+		// On some platforms (e.g. Linux), the passed-in timeval is
+		// updated by select(2). Make sure to reset to the full duration
+		// in case of an EINTR.
+		tv := unix.NsecToTimeval(int64(dur))
 		start := time.Now()
 		n, err := unix.Select(0, nil, nil, nil, &tv)
 		took = time.Since(start)