diff options
author | Paul Eggert <eggert@cs.ucla.edu> | 2020-02-16 12:47:52 -0800 |
---|---|---|
committer | Paul Eggert <eggert@cs.ucla.edu> | 2020-02-16 12:48:34 -0800 |
commit | f3243f20107435f620338aa15e1fdd5779d639fe (patch) | |
tree | d34407410197c6cc041aae58ff5ea87d31bafa9f | |
parent | c7cc0deae47dad9f68ba56fd569e1eb793f61b81 (diff) | |
download | gnulib-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-- | ChangeLog | 11 | ||||
-rw-r--r-- | lib/xnanosleep.c | 22 | ||||
-rw-r--r-- | m4/xnanosleep.m4 | 4 | ||||
-rw-r--r-- | modules/xnanosleep | 2 |
4 files changed, 35 insertions, 4 deletions
@@ -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 |