From 81af7394a23829719e2bddc0e814d8e0d71d41e2 Mon Sep 17 00:00:00 2001 From: Tobias Klauser Date: Sat, 16 Nov 2019 13:20:08 +0100 Subject: [PATCH] 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 TryBot-Result: Gobot Gobot Reviewed-by: Brad Fitzpatrick Reviewed-by: Ian Lance Taylor --- unix/syscall_linux_test.go | 48 ++++++++++++++++++++++++-------------- 1 file changed, 31 insertions(+), 17 deletions(-) diff --git a/unix/syscall_linux_test.go b/unix/syscall_linux_test.go index 8f4f1254..d28d5b5b 100644 --- a/unix/syscall_linux_test.go +++ b/unix/syscall_linux_test.go @@ -557,33 +557,47 @@ func TestSyncFileRange(t *testing.T) { } 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) }