unix: don't fail TestClockNanosleep on EINTR from ClockNanosleep

Continue the test and log the time slept in case of EINTR.

Fixes golang/go#35622

Change-Id: I4444b2500a5ae492aad27f3bcbc5f77ef3944447
Reviewed-on: https://go-review.googlesource.com/c/sys/+/207285
Run-TryBot: Tobias Klauser <tobias.klauser@gmail.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
Reviewed-by: Ian Lance Taylor <iant@golang.org>
diff --git a/unix/syscall_linux_test.go b/unix/syscall_linux_test.go
index 8f4f125..d28d5b5 100644
--- a/unix/syscall_linux_test.go
+++ b/unix/syscall_linux_test.go
@@ -557,33 +557,47 @@
 }
 
 func TestClockNanosleep(t *testing.T) {
-	delay := 100 * time.Millisecond
+	delay := 50 * time.Millisecond
 
 	// Relative timespec.
 	start := time.Now()
 	rel := unix.NsecToTimespec(delay.Nanoseconds())
-	err := unix.ClockNanosleep(unix.CLOCK_MONOTONIC, 0, &rel, nil)
-	if err == unix.ENOSYS || err == unix.EPERM {
-		t.Skip("clock_nanosleep syscall is not available, skipping test")
-	} else if err != nil {
-		t.Errorf("ClockNanosleep(CLOCK_MONOTONIC, 0, %#v, nil) = %v", &rel, err)
-	} else if slept := time.Since(start); slept < delay {
-		t.Errorf("ClockNanosleep(CLOCK_MONOTONIC, 0, %#v, nil) slept only %v", &rel, slept)
+	remain := unix.Timespec{}
+	for {
+		err := unix.ClockNanosleep(unix.CLOCK_MONOTONIC, 0, &rel, &remain)
+		if err == unix.ENOSYS || err == unix.EPERM {
+			t.Skip("clock_nanosleep syscall is not available, skipping test")
+		} else if err == unix.EINTR {
+			t.Logf("ClockNanosleep interrupted after %v", time.Since(start))
+			rel = remain
+			continue
+		} else if err != nil {
+			t.Errorf("ClockNanosleep(CLOCK_MONOTONIC, 0, %#v, nil) = %v", &rel, err)
+		} else if slept := time.Since(start); slept < delay {
+			t.Errorf("ClockNanosleep(CLOCK_MONOTONIC, 0, %#v, nil) slept only %v", &rel, slept)
+		}
+		break
 	}
 
 	// Absolute timespec.
-	start = time.Now()
-	until := start.Add(delay)
-	abs := unix.NsecToTimespec(until.UnixNano())
-	err = unix.ClockNanosleep(unix.CLOCK_REALTIME, unix.TIMER_ABSTIME, &abs, nil)
-	if err != nil {
-		t.Errorf("ClockNanosleep(CLOCK_REALTIME, TIMER_ABSTIME, %#v (=%v), nil) = %v", &abs, until, err)
-	} else if slept := time.Since(start); slept < delay {
-		t.Errorf("ClockNanosleep(CLOCK_REALTIME, TIMER_ABSTIME, %#v (=%v), nil) slept only %v", &abs, until, slept)
+	for {
+		start = time.Now()
+		until := start.Add(delay)
+		abs := unix.NsecToTimespec(until.UnixNano())
+		err := unix.ClockNanosleep(unix.CLOCK_REALTIME, unix.TIMER_ABSTIME, &abs, nil)
+		if err != nil {
+			t.Errorf("ClockNanosleep(CLOCK_REALTIME, TIMER_ABSTIME, %#v (=%v), nil) = %v", &abs, until, err)
+		} else if err == unix.EINTR {
+			t.Logf("ClockNanosleep interrupted after %v", time.Since(start))
+			continue
+		} else if slept := time.Since(start); slept < delay {
+			t.Errorf("ClockNanosleep(CLOCK_REALTIME, TIMER_ABSTIME, %#v (=%v), nil) slept only %v", &abs, until, slept)
+		}
+		break
 	}
 
 	// Invalid clock. clock_nanosleep(2) says EINVAL, but it’s actually EOPNOTSUPP.
-	err = unix.ClockNanosleep(unix.CLOCK_THREAD_CPUTIME_ID, 0, &rel, nil)
+	err := unix.ClockNanosleep(unix.CLOCK_THREAD_CPUTIME_ID, 0, &rel, nil)
 	if err != unix.EINVAL && err != unix.EOPNOTSUPP {
 		t.Errorf("ClockNanosleep(CLOCK_THREAD_CPUTIME_ID, 0, %#v, nil) = %v, want EINVAL or EOPNOTSUPP", &rel, err)
 	}