xnanosleep: prefer pause, and get remaining time
authorPaul Eggert <eggert@cs.ucla.edu>
Sun, 16 Feb 2020 20:47:52 +0000 (12:47 -0800)
committerPaul Eggert <eggert@cs.ucla.edu>
Sun, 16 Feb 2020 20:48:34 +0000 (12:48 -0800)
Problem reported by Vladimir Panteleev in:
https://lists.gnu.org/r/bug-gnulib/2020-02/msg00052.html
* lib/xnanosleep.c: Include intprops.h, unistd.h.
(xnanosleep) [HAVE_PAUSE]: Prefer pause when sleeping infinitely.
(xnanosleep): Obtain remaining time when nanosleep is interrupted.
* m4/xnanosleep.m4 (gl_XNANOSLEEP): Check for 'pause'.
* modules/xnanosleep (Depends-on): Add intprops, unistd.

ChangeLog
lib/xnanosleep.c
m4/xnanosleep.m4
modules/xnanosleep

index beacc09263366d1aba095f46cf8276cc5806fb2f..4e3f51ba23983e2035d2aca1dd62a5bc5c4489ef 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,14 @@
+2020-02-16  Paul Eggert  <eggert@cs.ucla.edu>
+
+       xnanosleep: prefer pause, and get remaining time
+       Problem reported by Vladimir Panteleev in:
+       https://lists.gnu.org/r/bug-gnulib/2020-02/msg00052.html
+       * lib/xnanosleep.c: Include intprops.h, unistd.h.
+       (xnanosleep) [HAVE_PAUSE]: Prefer pause when sleeping infinitely.
+       (xnanosleep): Obtain remaining time when nanosleep is interrupted.
+       * m4/xnanosleep.m4 (gl_XNANOSLEEP): Check for 'pause'.
+       * modules/xnanosleep (Depends-on): Add intprops, unistd.
+
 2020-02-16  Bruno Haible  <bruno@clisp.org>
 
        lchmod: Improve cross-compilation guess.
index 5774f75f392a6e7d6e43fa18a3eee02f1e55b645..8619c6df69396de22db6412c4cc74be7dc5b81e8 100644 (file)
 
 #include "xnanosleep.h"
 
+#include <intprops.h>
 #include <timespec.h>
 
 #include <errno.h>
 #include <time.h>
+#include <unistd.h>
 
 /* Sleep until the time (call it WAKE_UP_TIME) specified as
    SECONDS seconds after the time this function is called.
 int
 xnanosleep (double seconds)
 {
+#if HAVE_PAUSE
+  if (1.0 + TYPE_MAXIMUM (time_t) <= seconds)
+    {
+      do
+        pause ();
+      while (errno == EINTR);
+
+      /* pause failed (!); fall back on repeated nanosleep calls.  */
+    }
+#endif
+
   struct timespec ts_sleep = dtotimespec (seconds);
 
   for (;;)
@@ -46,9 +59,14 @@ xnanosleep (double seconds)
          set errno to EINTR.  nanosleep from linux-2.6.10, as well as
          implementations by (all?) other vendors, doesn't return -1
          in that case;  either it continues sleeping (if time remains)
-         or it returns zero (if the wake-up time has passed).  */
+         or it returns zero (if the wake-up time has passed).
+
+         Gnulib's replacement nanosleep sometimes does not update
+         TS_SLEEP, and it is possible some kernels have a similar bug.
+         However, this merely causes xnanosleep to sleep longer than
+         necessary, which is not a correctness bug.  */
       errno = 0;
-      if (nanosleep (&ts_sleep, NULL) == 0)
+      if (nanosleep (&ts_sleep, &ts_sleep) == 0)
         break;
       if (errno != EINTR && errno != 0)
         return -1;
index 5f305f8640d98ed6156822d22d6ad777e05d0d80..88454ae01f4206816a13e8eb8c98d1da39349b43 100644 (file)
@@ -1,4 +1,4 @@
-#serial 5
+#serial 6
 dnl Copyright (C) 2005-2006, 2009-2020 Free Software Foundation, Inc.
 dnl This file is free software; the Free Software Foundation
 dnl gives unlimited permission to copy and/or distribute it,
@@ -8,5 +8,5 @@ dnl Written by Paul Eggert.
 
 AC_DEFUN([gl_XNANOSLEEP],
 [
-  :
+  AC_CHECK_FUNCS_ONCE([pause])
 ])
index 0a2b373eac87c2260a8ec5729fab7179bcb33939..cc9069cb2571103362b721db51b6f68c6a215248 100644 (file)
@@ -8,8 +8,10 @@ m4/xnanosleep.m4
 
 Depends-on:
 dtotimespec
+intprops
 nanosleep
 time
+unistd
 
 configure.ac:
 gl_XNANOSLEEP