+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.
#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 (;;)
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;
-#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,
AC_DEFUN([gl_XNANOSLEEP],
[
- :
+ AC_CHECK_FUNCS_ONCE([pause])
])