summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Eggert <eggert@cs.ucla.edu>2020-02-16 12:47:52 -0800
committerPaul Eggert <eggert@cs.ucla.edu>2020-02-16 12:48:34 -0800
commitf3243f20107435f620338aa15e1fdd5779d639fe (patch)
treed34407410197c6cc041aae58ff5ea87d31bafa9f
parentc7cc0deae47dad9f68ba56fd569e1eb793f61b81 (diff)
downloadgnulib-f3243f20107435f620338aa15e1fdd5779d639fe.tar.gz
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.
-rw-r--r--ChangeLog11
-rw-r--r--lib/xnanosleep.c22
-rw-r--r--m4/xnanosleep.m44
-rw-r--r--modules/xnanosleep2
4 files changed, 35 insertions, 4 deletions
diff --git a/ChangeLog b/ChangeLog
index beacc09263..4e3f51ba23 100644
--- 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.
diff --git a/lib/xnanosleep.c b/lib/xnanosleep.c
index 5774f75f39..8619c6df69 100644
--- a/lib/xnanosleep.c
+++ b/lib/xnanosleep.c
@@ -22,10 +22,12 @@
#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.
@@ -37,6 +39,17 @@
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;
diff --git a/m4/xnanosleep.m4 b/m4/xnanosleep.m4
index 5f305f8640..88454ae01f 100644
--- a/m4/xnanosleep.m4
+++ b/m4/xnanosleep.m4
@@ -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])
])
diff --git a/modules/xnanosleep b/modules/xnanosleep
index 0a2b373eac..cc9069cb25 100644
--- a/modules/xnanosleep
+++ b/modules/xnanosleep
@@ -8,8 +8,10 @@ m4/xnanosleep.m4
Depends-on:
dtotimespec
+intprops
nanosleep
time
+unistd
configure.ac:
gl_XNANOSLEEP