>From f3243f20107435f620338aa15e1fdd5779d639fe Mon Sep 17 00:00:00 2001 From: Paul Eggert Date: Sun, 16 Feb 2020 12:47:52 -0800 Subject: [PATCH] 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. --- ChangeLog | 11 +++++++++++ lib/xnanosleep.c | 22 ++++++++++++++++++++-- m4/xnanosleep.m4 | 4 ++-- modules/xnanosleep | 2 ++ 4 files changed, 35 insertions(+), 4 deletions(-) diff --git a/ChangeLog b/ChangeLog index beacc0926..4e3f51ba2 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,14 @@ +2020-02-16 Paul Eggert + + 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 lchmod: Improve cross-compilation guess. diff --git a/lib/xnanosleep.c b/lib/xnanosleep.c index 5774f75f3..8619c6df6 100644 --- a/lib/xnanosleep.c +++ b/lib/xnanosleep.c @@ -22,10 +22,12 @@ #include "xnanosleep.h" +#include #include #include #include +#include /* 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 5f305f864..88454ae01 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 0a2b373ea..cc9069cb2 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 -- 2.17.1