bug-gnulib
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: usleep


From: Eric Blake
Subject: Re: usleep
Date: Wed, 18 Nov 2009 22:16:05 -0700
User-agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.1.23) Gecko/20090812 Thunderbird/2.0.0.23 Mnenhy/0.7.6.666

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

According to Eric Blake on 11/18/2009 5:56 PM:
> Yep.  I'll fix it in my respin.  Besides, I found out that rpl_nanosleep
> needs the same bug fix, and not only that, but it has a logic bug - it
> ignores EINTR, forcing the sleep to last until a fatal signal or the
> entire time has elapsed, on systems where the remaining time properly
> decreases.  Worse, it goes into an infinite 100% CPU busy loop on cygwin

Actually, the infloop occurs on any platform with nanosleep, if tv_nsec is
out of range.  coreutils' sleep(1) was immune, since it always used valid
arguments.

At any rate, here's what I'm now testing, it has passed on cygwin, 64-bit
Linux, and Solaris.  The nanosleep code is a complete rewrite, and is
actually lighter-weight (no need to use clock_gettime).  Unfortunately,
cross-compiling to mingw is still failing two tests; so some more coding
efforts are needed beyond this preliminary patch.

test-nanosleep.c:60: assertion failed
FAIL: test-nanosleep.exe

[no message; often indicative of stack overflow]
FAIL: test-select-out.sh

- --
Don't work too hard, make some time for fun as well!

Eric Blake             address@hidden
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.9 (Cygwin)
Comment: Public key at home.comcast.net/~ericblake/eblake.gpg
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org/

iEYEARECAAYFAksE1JUACgkQ84KuGfSFAYB4aACePTAguHKT8tFaLZrzt6RmXdm3
3h4AoKhykPz9QScc3obGsRW4seBzwnhh
=TUNJ
-----END PGP SIGNATURE-----
From e1861efe151da62ff1c8ca10b42fec99f9409a8f Mon Sep 17 00:00:00 2001
From: Eric Blake <address@hidden>
Date: Wed, 18 Nov 2009 20:07:44 -0700
Subject: [PATCH 1/4] sleep: work around cygwin bug

On cygwin 1.5.x, sleep amounts larger than 49.7 days (2**32
milliseconds) failed instantly, but with a garbage return
value from uninitialized memory.

* lib/sleep.c (rpl_sleep): Work around the bug.
* m4/sleep.m4 (gl_FUNC_SLEEP): Detect the bug.
(gl_PREREQ_SLEEP): Delete unused macro.
* modules/sleep (Depends-on): Add verify.
* m4/unistd_h.m4 (gl_UNISTD_H_DEFAULTS): Add default.
* modules/unistd (Makefile.am): Substitute witness.
* lib/unistd.in.h (sleep): Update prototype.
* doc/posix-functions/sleep.texi (sleep): Document the bug.
* tests/test-sleep.c (main) [HAVE_DECL_ALARM]: Test it.
* modules/sleep-tests (Depends-on): Check for alarm.

Signed-off-by: Eric Blake <address@hidden>
---
 ChangeLog                      |   12 ++++++++++++
 doc/posix-functions/sleep.texi |    3 +++
 lib/sleep.c                    |   33 +++++++++++++++++++++++++++++++--
 lib/unistd.in.h                |    6 +++++-
 m4/sleep.m4                    |   37 +++++++++++++++++++++++++++++++------
 m4/unistd_h.m4                 |    3 ++-
 modules/sleep                  |    2 ++
 modules/sleep-tests            |    2 +-
 modules/unistd                 |    1 +
 tests/test-sleep.c             |   40 ++++++++++++++++++++++++++++++----------
 10 files changed, 118 insertions(+), 21 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index a868d1d..ac96813 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,17 @@
 2009-11-18  Eric Blake  <address@hidden>

+       sleep: work around cygwin bug
+       * lib/sleep.c (rpl_sleep): Work around the bug.
+       * m4/sleep.m4 (gl_FUNC_SLEEP): Detect the bug.
+       (gl_PREREQ_SLEEP): Delete unused macro.
+       * modules/sleep (Depends-on): Add verify.
+       * m4/unistd_h.m4 (gl_UNISTD_H_DEFAULTS): Add default.
+       * modules/unistd (Makefile.am): Substitute witness.
+       * lib/unistd.in.h (sleep): Update prototype.
+       * doc/posix-functions/sleep.texi (sleep): Document the bug.
+       * tests/test-sleep.c (main) [HAVE_DECL_ALARM]: Test it.
+       * modules/sleep-tests (Depends-on): Check for alarm.
+
        tests: avoid false negative with --with-packager
        * tests/test-version-etc.sh: Discard packager information.
        * tests/test-argp-version-etc-1.sh: Likewise.
diff --git a/doc/posix-functions/sleep.texi b/doc/posix-functions/sleep.texi
index 9a7a74f..6df8693 100644
--- a/doc/posix-functions/sleep.texi
+++ b/doc/posix-functions/sleep.texi
@@ -15,6 +15,9 @@ sleep
 This function takes milliseconds as argument and returns @code{void} on some
 platforms:
 mingw (2005 and older).
address@hidden
+This function cannot sleep longer than 49.7 days on some platforms:
+Cygwin 1.5.x.
 @end itemize

 Portability problems not fixed by Gnulib:
diff --git a/lib/sleep.c b/lib/sleep.c
index 9c56b9b..90b482c 100644
--- a/lib/sleep.c
+++ b/lib/sleep.c
@@ -1,5 +1,5 @@
 /* Pausing execution of the current thread.
-   Copyright (C) 2007 Free Software Foundation, Inc.
+   Copyright (C) 2007, 2009 Free Software Foundation, Inc.
    Written by Bruno Haible <address@hidden>, 2007.

    This program is free software: you can redistribute it and/or modify
@@ -20,6 +20,10 @@
 /* Specification.  */
 #include <unistd.h>

+#include <limits.h>
+
+#include "verify.h"
+
 #if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__

 # define WIN32_LEAN_AND_MEAN  /* avoid including junk */
@@ -39,7 +43,32 @@ sleep (unsigned int seconds)
   return remaining;
 }

-#else
+#elif HAVE_SLEEP
+
+# undef sleep
+
+/* Guarantee unlimited sleep and a reasonable return value.  Cygwin
+   1.5.x rejects attempts to sleep more than 49.7 days (2**32
+   milliseconds), but uses uninitialized memory which results in a
+   garbage answer.  */
+unsigned int
+rpl_sleep (unsigned int seconds)
+{
+  /* This requires int larger than 16 bits.  */
+  verify (UINT_MAX / 49 / 24 / 60 / 60);
+  const unsigned int limit = 49 * 24 * 60 * 60;
+  while (limit < seconds)
+    {
+      unsigned int result;
+      seconds -= limit;
+      result = sleep (limit);
+      if (result)
+        return seconds + result;
+    }
+  return sleep (seconds);
+}
+
+#else /* !HAVE_SLEEP */

  #error "Please port gnulib sleep.c to your platform, possibly using usleep() 
or select(), then report this to bug-gnulib."

diff --git a/lib/unistd.in.h b/lib/unistd.in.h
index 30f7bdd..9a9a671 100644
--- a/lib/unistd.in.h
+++ b/lib/unistd.in.h
@@ -714,11 +714,15 @@ extern int rmdir (char const *name);


 #if @GNULIB_SLEEP@
+# if @REPLACE_SLEEP@
+#  undef sleep
+#  define sleep rpl_sleep
+# endif
 /* Pause the execution of the current thread for N seconds.
    Returns the number of seconds left to sleep.
    See the POSIX:2001 specification
    <http://www.opengroup.org/susv3xsh/sleep.html>.  */
-# if address@hidden@
+# if address@hidden@ || @REPLACE_SLEEP@
 extern unsigned int sleep (unsigned int n);
 # endif
 #elif defined GNULIB_POSIXCHECK
diff --git a/m4/sleep.m4 b/m4/sleep.m4
index 474ba07..c59b383 100644
--- a/m4/sleep.m4
+++ b/m4/sleep.m4
@@ -1,5 +1,5 @@
-# sleep.m4 serial 2
-dnl Copyright (C) 2007-2008 Free Software Foundation, Inc.
+# sleep.m4 serial 3
+dnl Copyright (C) 2007-2009 Free Software Foundation, Inc.
 dnl This file is free software; the Free Software Foundation
 dnl gives unlimited permission to copy and/or distribute it,
 dnl with or without modifications, as long as this notice is preserved.
@@ -13,12 +13,37 @@ AC_DEFUN([gl_FUNC_SLEEP],
   dnl it takes the number of milliseconds as argument and returns void.
   dnl mingw does not declare this function.
   AC_CHECK_DECLS([sleep], , , [#include <unistd.h>])
+  AC_CHECK_FUNCS_ONCE([sleep])
   if test $ac_cv_have_decl_sleep != yes; then
     HAVE_SLEEP=0
     AC_LIBOBJ([sleep])
-    gl_PREREQ_SLEEP
+  else
+    dnl Cygwin 1.5.x has a bug where sleep can't exceed 49.7 days.
+    AC_CACHE_CHECK([for working sleep], [gl_cv_func_sleep_works],
+      [AC_RUN_IFELSE([AC_LANG_PROGRAM([[
+#include <errno.h>
+#include <unistd.h>
+#include <signal.h>
+static void
+handle_alarm (int sig)
+{
+  if (sig != SIGALRM)
+    _exit (2);
+}
+]], [[
+    /* Failure to compile this test due to missing alarm is okay,
+       since all such platforms (mingw) also lack sleep.  */
+    unsigned int pentecost = 50 * 24 * 60 * 60; /* 50 days.  */
+    unsigned int remaining;
+    signal (SIGALRM, handle_alarm);
+    alarm (1);
+    remaining = sleep (pentecost);
+    return !(pentecost - 10 < remaining && remaining <= pentecost);]])],
+      [gl_cv_func_sleep_works=yes], [gl_cv_func_sleep_works=no],
+      [gl_cv_func_sleep_works="guessing no"])])
+    if test "$gl_cv_func_sleep_works" != yes; then
+      REPLACE_SLEEP=1
+      AC_LIBOBJ([sleep])
+    fi
   fi
 ])
-
-# Prerequisites of lib/sleep.c.
-AC_DEFUN([gl_PREREQ_SLEEP], [:])
diff --git a/m4/unistd_h.m4 b/m4/unistd_h.m4
index 25bdb59..0a5b5d5 100644
--- a/m4/unistd_h.m4
+++ b/m4/unistd_h.m4
@@ -1,4 +1,4 @@
-# unistd_h.m4 serial 35
+# unistd_h.m4 serial 36
 dnl Copyright (C) 2006-2009 Free Software Foundation, Inc.
 dnl This file is free software; the Free Software Foundation
 dnl gives unlimited permission to copy and/or distribute it,
@@ -113,6 +113,7 @@ AC_DEFUN([gl_UNISTD_H_DEFAULTS],
   REPLACE_LSEEK=0;        AC_SUBST([REPLACE_LSEEK])
   REPLACE_READLINK=0;     AC_SUBST([REPLACE_READLINK])
   REPLACE_RMDIR=0;        AC_SUBST([REPLACE_RMDIR])
+  REPLACE_SLEEP=0;        AC_SUBST([REPLACE_SLEEP])
   REPLACE_SYMLINK=0;      AC_SUBST([REPLACE_SYMLINK])
   REPLACE_UNLINK=0;       AC_SUBST([REPLACE_UNLINK])
   REPLACE_UNLINKAT=0;     AC_SUBST([REPLACE_UNLINKAT])
diff --git a/modules/sleep b/modules/sleep
index d8af514..e859e59 100644
--- a/modules/sleep
+++ b/modules/sleep
@@ -6,7 +6,9 @@ lib/sleep.c
 m4/sleep.m4

 Depends-on:
+stdint
 unistd
+verify

 configure.ac:
 gl_FUNC_SLEEP
diff --git a/modules/sleep-tests b/modules/sleep-tests
index 91de2ee..0871d51 100644
--- a/modules/sleep-tests
+++ b/modules/sleep-tests
@@ -4,8 +4,8 @@ tests/test-sleep.c
 Depends-on:

 configure.ac:
+AC_CHECK_DECLS_ONCE([alarm])

 Makefile.am:
 TESTS += test-sleep
 check_PROGRAMS += test-sleep
-
diff --git a/modules/unistd b/modules/unistd
index 008ccdf..1282e53 100644
--- a/modules/unistd
+++ b/modules/unistd
@@ -105,6 +105,7 @@ unistd.h: unistd.in.h
              -e 's|@''REPLACE_LSEEK''@|$(REPLACE_LSEEK)|g' \
              -e 's|@''REPLACE_READLINK''@|$(REPLACE_READLINK)|g' \
              -e 's|@''REPLACE_RMDIR''@|$(REPLACE_RMDIR)|g' \
+             -e 's|@''REPLACE_SLEEP''@|$(REPLACE_SLEEP)|g' \
              -e 's|@''REPLACE_SYMLINK''@|$(REPLACE_SYMLINK)|g' \
              -e 's|@''REPLACE_UNLINK''@|$(REPLACE_UNLINK)|g' \
              -e 's|@''REPLACE_UNLINKAT''@|$(REPLACE_UNLINKAT)|g' \
diff --git a/tests/test-sleep.c b/tests/test-sleep.c
index ed5a5a0..48abce1 100644
--- a/tests/test-sleep.c
+++ b/tests/test-sleep.c
@@ -1,5 +1,5 @@
 /* Test of sleep() function.
-   Copyright (C) 2007-2008 Free Software Foundation, Inc.
+   Copyright (C) 2007-2009 Free Software Foundation, Inc.

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
@@ -20,21 +20,31 @@

 #include <unistd.h>

+#include <signal.h>
 #include <stdio.h>
 #include <stdlib.h>

 #define ASSERT(expr) \
-  do                                                                        \
-    {                                                                       \
-      if (!(expr))                                                          \
-        {                                                                   \
+  do                                                                         \
+    {                                                                        \
+      if (!(expr))                                                           \
+        {                                                                    \
           fprintf (stderr, "%s:%d: assertion failed\n", __FILE__, __LINE__); \
-          fflush (stderr);                                                  \
-          abort ();                                                         \
-        }                                                                   \
-    }                                                                       \
+          fflush (stderr);                                                   \
+          abort ();                                                          \
+        }                                                                    \
+    }                                                                        \
   while (0)

+#if HAVE_DECL_ALARM
+static void
+handle_alarm (int sig)
+{
+  if (sig != SIGALRM)
+    _exit (1);
+}
+#endif
+
 int
 main()
 {
@@ -42,6 +52,16 @@ main()

   ASSERT (sleep (0) == 0);

+#if HAVE_DECL_ALARM
+  {
+    const unsigned int pentecost = 50 * 24 * 60 * 60; /* 50 days.  */
+    unsigned int remaining;
+    signal (SIGALRM, handle_alarm);
+    alarm (1);
+    remaining = sleep (pentecost);
+    ASSERT (pentecost - 10 < remaining && remaining <= pentecost);
+  }
+#endif
+
   return 0;
 }
-
-- 
1.6.5.rc1


From 3ae558b1bc0ff294c6f097504a6fd8bd983ab4bc Mon Sep 17 00:00:00 2001
From: Eric Blake <address@hidden>
Date: Wed, 18 Nov 2009 20:10:42 -0700
Subject: [PATCH 2/4] nanosleep: work around cygwin bug

Cygwin 1.5.x mistakenly failed with EINVAL for a duration longer
than 49.7 days (2**32 milliseconds).  Meanwhile, the existing
code for HAVE_BUG_BIG_NANOSLEEP would infloop, instead of return
failure, for invalid arguments.

* lib/nanosleep.c (rpl_nanosleep) [HAVE_BUG_BIG_NANOSLEEP]:
Fix logic bug when nanosleep fails.  Work around cygwin 1.5.x
bug.
(getnow): Delete, not needed.
* m4/nanosleep.m4 (gl_FUNC_NANOSLEEP): No longer require
LIB_CLOCK_GETTIME.
* modules/nanosleep (Depends-on): Add intprops and verify.  Drop
clock-time, gettime.
* doc/posix-functions/nanosleep.texi (nanosleep): Document the
bug.
* modules/nanosleep-tests: New test.
* tests/test-nanosleep.c: New file.

Signed-off-by: Eric Blake <address@hidden>
---
 ChangeLog                          |   14 +++++
 doc/posix-functions/nanosleep.texi |    3 +
 lib/nanosleep.c                    |   82 ++++++++++++++-----------------
 m4/nanosleep.m4                    |    9 +---
 modules/nanosleep                  |    4 +-
 modules/nanosleep-tests            |   12 +++++
 tests/test-nanosleep.c             |   94 ++++++++++++++++++++++++++++++++++++
 7 files changed, 162 insertions(+), 56 deletions(-)
 create mode 100644 modules/nanosleep-tests
 create mode 100644 tests/test-nanosleep.c

diff --git a/ChangeLog b/ChangeLog
index ac96813..5bd4205 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,19 @@
 2009-11-18  Eric Blake  <address@hidden>

+       nanosleep: work around cygwin bug
+       * lib/nanosleep.c (rpl_nanosleep) [HAVE_BUG_BIG_NANOSLEEP]:
+       Fix logic bug when nanosleep fails.  Work around cygwin 1.5.x
+       bug.
+       (getnow): Delete, not needed.
+       * m4/nanosleep.m4 (gl_FUNC_NANOSLEEP): No longer require
+       LIB_CLOCK_GETTIME.
+       * modules/nanosleep (Depends-on): Add intprops and verify.  Drop
+       clock-time, gettime.
+       * doc/posix-functions/nanosleep.texi (nanosleep): Document the
+       bug.
+       * modules/nanosleep-tests: New test.
+       * tests/test-nanosleep.c: New file.
+
        sleep: work around cygwin bug
        * lib/sleep.c (rpl_sleep): Work around the bug.
        * m4/sleep.m4 (gl_FUNC_SLEEP): Detect the bug.
diff --git a/doc/posix-functions/nanosleep.texi 
b/doc/posix-functions/nanosleep.texi
index a44ffa7..f4f0b56 100644
--- a/doc/posix-functions/nanosleep.texi
+++ b/doc/posix-functions/nanosleep.texi
@@ -19,6 +19,9 @@ nanosleep
 This function mishandles large arguments when interrupted by a signal on some
 platforms:
 Linux 64-bit, Solaris 64-bit.
address@hidden
+This function cannot sleep longer than 49.7 days on some platforms:
+Cygwin 1.5.x.
 @end itemize

 Portability problems not fixed by Gnulib:
diff --git a/lib/nanosleep.c b/lib/nanosleep.c
index 7a7cc02..a9311f8 100644
--- a/lib/nanosleep.c
+++ b/lib/nanosleep.c
@@ -1,7 +1,7 @@
 /* Provide a replacement for the POSIX nanosleep function.

-   Copyright (C) 1999, 2000, 2002, 2004, 2005, 2006, 2007, 2008 Free
-   Software Foundation, Inc.
+   Copyright (C) 1999, 2000, 2002, 2004, 2005, 2006, 2007, 2008, 2009
+   Free Software Foundation, Inc.

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
@@ -22,8 +22,9 @@

 #include <time.h>

+#include "intprops.h"
 #include "sig-handler.h"
-#include "timespec.h"
+#include "verify.h"

 #include <stdbool.h>
 #include <stdio.h>
@@ -42,56 +43,45 @@ enum { BILLION = 1000 * 1000 * 1000 };

 #if HAVE_BUG_BIG_NANOSLEEP

-static void
-getnow (struct timespec *t)
-{
-# if defined CLOCK_MONOTONIC && HAVE_CLOCK_GETTIME
-  if (clock_gettime (CLOCK_MONOTONIC, t) == 0)
-    return;
-# endif
-  gettime (t);
-}
-
 int
 rpl_nanosleep (const struct timespec *requested_delay,
               struct timespec *remaining_delay)
 {
   /* nanosleep mishandles large sleeps due to internal overflow
-     problems, so check that the proper amount of time has actually
-     elapsed.  */
-
-  struct timespec delay = *requested_delay;
-  struct timespec t0;
-  getnow (&t0);
-
-  for (;;)
+     problems.  The worst known case of this is cygwin 1.5.x, which
+     can't sleep more than 49.7 days (2**32 milliseconds).  Solve this
+     by breaking the sleep up into smaller chunks.  Verify that time_t
+     is large enough.  */
+  verify (TYPE_MAXIMUM (time_t) / 49 / 24 / 60 / 60);
+  const time_t limit = 49 * 24 * 60 * 60;
+  time_t seconds = requested_delay->tv_sec;
+  struct timespec intermediate;
+  intermediate.tv_nsec = 0;
+
+  while (limit < seconds)
     {
-      int r = nanosleep (&delay, remaining_delay);
-      if (r == 0)
-       {
-         time_t secs_sofar;
-         struct timespec now;
-         getnow (&now);
-
-         secs_sofar = now.tv_sec - t0.tv_sec;
-         if (requested_delay->tv_sec < secs_sofar)
-           return 0;
-         delay.tv_sec = requested_delay->tv_sec - secs_sofar;
-         delay.tv_nsec = requested_delay->tv_nsec - (now.tv_nsec - t0.tv_nsec);
-         if (delay.tv_nsec < 0)
-           {
-             if (delay.tv_sec == 0)
-               return 0;
-             delay.tv_nsec += BILLION;
-             delay.tv_sec--;
-           }
-         else if (BILLION <= delay.tv_nsec)
-           {
-             delay.tv_nsec -= BILLION;
-             delay.tv_sec++;
-           }
-       }
+      int result;
+      intermediate.tv_sec = limit;
+      result = nanosleep (&intermediate, remaining_delay);
+      seconds -= limit;
+      if (result)
+        {
+          if (remaining_delay)
+            {
+              remaining_delay->tv_sec += seconds;
+              remaining_delay->tv_nsec += requested_delay->tv_nsec;
+              if (BILLION <= requested_delay->tv_nsec)
+                {
+                  remaining_delay->tv_sec++;
+                  remaining_delay->tv_nsec -= BILLION;
+                }
+            }
+          return result;
+        }
     }
+  intermediate.tv_sec = seconds;
+  intermediate.tv_nsec = requested_delay->tv_nsec;
+  return nanosleep (&intermediate, remaining_delay);
 }

 #else
diff --git a/m4/nanosleep.m4 b/m4/nanosleep.m4
index d991b61..211b367 100644
--- a/m4/nanosleep.m4
+++ b/m4/nanosleep.m4
@@ -1,4 +1,4 @@
-# serial 28
+# serial 29

 dnl From Jim Meyering.
 dnl Check for the nanosleep function.
@@ -17,7 +17,6 @@ AC_DEFUN([gl_FUNC_NANOSLEEP],
  AC_REQUIRE([gl_USE_SYSTEM_EXTENSIONS])

  AC_REQUIRE([gl_HEADER_TIME_H_DEFAULTS])
- AC_REQUIRE([gl_CLOCK_TIME])
  AC_CHECK_HEADERS_ONCE([sys/time.h])

  nanosleep_save_libs=$LIBS
@@ -103,12 +102,6 @@ AC_DEFUN([gl_FUNC_NANOSLEEP],
     if test "$gl_cv_func_nanosleep" = 'no (mishandles large arguments)'; then
       AC_DEFINE([HAVE_BUG_BIG_NANOSLEEP], [1],
        [Define to 1 if nanosleep mishandles large arguments.])
-      for ac_lib in $LIB_CLOCK_GETTIME; do
-       case " $LIB_NANOSLEEP " in
-       *" $ac_lib "*) ;;
-       *) LIB_NANOSLEEP="$LIB_NANOSLEEP $ac_lib";;
-       esac
-      done
     fi
     AC_LIBOBJ([nanosleep])
     gl_PREREQ_NANOSLEEP
diff --git a/modules/nanosleep b/modules/nanosleep
index a652e53..d457b6f 100644
--- a/modules/nanosleep
+++ b/modules/nanosleep
@@ -6,9 +6,8 @@ lib/nanosleep.c
 m4/nanosleep.m4

 Depends-on:
-clock-time
 extensions
-gettime
+intprops
 multiarch
 select
 sigaction
@@ -16,6 +15,7 @@ stdbool
 sys_select
 sys_time
 time
+verify

 configure.ac:
 gl_FUNC_NANOSLEEP
diff --git a/modules/nanosleep-tests b/modules/nanosleep-tests
new file mode 100644
index 0000000..67e6d4e
--- /dev/null
+++ b/modules/nanosleep-tests
@@ -0,0 +1,12 @@
+Files:
+tests/test-nanosleep.c
+
+Depends-on:
+
+configure.ac:
+AC_CHECK_DECLS_ONCE([alarm])
+
+Makefile.am:
+TESTS += test-nanosleep
+check_PROGRAMS += test-nanosleep
+test_nanosleep_LDADD = $(LDADD) $(LIB_NANOSLEEP)
diff --git a/tests/test-nanosleep.c b/tests/test-nanosleep.c
new file mode 100644
index 0000000..eb4bef6
--- /dev/null
+++ b/tests/test-nanosleep.c
@@ -0,0 +1,94 @@
+/* Test of nanosleep() function.
+   Copyright (C) 2009 Free Software Foundation, Inc.
+
+   This program is free software: you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+/* Written by Eric Blake <address@hidden>, 2009.  */
+
+#include <config.h>
+
+#include <time.h>
+
+#include <errno.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include "intprops.h"
+
+#define ASSERT(expr) \
+  do                                                                         \
+    {                                                                        \
+      if (!(expr))                                                           \
+        {                                                                    \
+          fprintf (stderr, "%s:%d: assertion failed\n", __FILE__, __LINE__); \
+          fflush (stderr);                                                   \
+          abort ();                                                          \
+        }                                                                    \
+    }                                                                        \
+  while (0)
+
+#if HAVE_DECL_ALARM
+static void
+handle_alarm (int sig)
+{
+  if (sig != SIGALRM)
+    _exit (1);
+}
+#endif
+
+int
+main()
+{
+  struct timespec ts;
+
+  ts.tv_sec = 1000;
+  ts.tv_nsec = -1;
+  errno = 0;
+  ASSERT (nanosleep (&ts, NULL) == -1);
+  ASSERT (errno == EINVAL);
+  ts.tv_nsec = 1000000000;
+  errno = 0;
+  ASSERT (nanosleep (&ts, NULL) == -1);
+  ASSERT (errno == EINVAL);
+
+  ts.tv_sec = 0;
+  ts.tv_nsec = 1;
+  ASSERT (nanosleep (&ts, &ts) == 0);
+  /* Remaining time is only defined on EINTR failure; but on success,
+     it is typically either 0 or unchanged from input.  At any rate,
+     it shouldn't be randomly changed to unrelated values.  */
+  ASSERT (ts.tv_sec == 0);
+  ASSERT (ts.tv_nsec == 0 || ts.tv_nsec == 1);
+  ts.tv_nsec = 0;
+  ASSERT (nanosleep (&ts, NULL) == 0);
+
+#if HAVE_DECL_ALARM
+  {
+    const time_t pentecost = 50 * 24 * 60 * 60; /* 50 days.  */
+    signal (SIGALRM, handle_alarm);
+    alarm (1);
+    ts.tv_sec = pentecost;
+    ts.tv_nsec = 999999999;
+    errno = 0;
+    ASSERT (nanosleep (&ts, &ts) == -1);
+    ASSERT (errno == EINTR);
+    ASSERT (pentecost - 10 < ts.tv_sec && ts.tv_sec <= pentecost);
+    ASSERT (0 <= ts.tv_nsec && ts.tv_nsec <= 999999999);
+  }
+#endif
+
+  return 0;
+}
-- 
1.6.5.rc1


From 65b314a386dedd0ff089ad69ed0e213a9249eb09 Mon Sep 17 00:00:00 2001
From: Eric Blake <address@hidden>
Date: Wed, 18 Nov 2009 21:46:35 -0700
Subject: [PATCH 3/4] build: avoid compiler warnings

Silence some warnings found on mingw.

* lib/select.c (rpl_select): Delete unused variable.
* lib/setsockopt.c (rpl_setsockopt): Avoid incompatible pointer.

Signed-off-by: Eric Blake <address@hidden>
---
 ChangeLog        |    6 ++++++
 lib/select.c     |    2 --
 lib/setsockopt.c |    3 ++-
 3 files changed, 8 insertions(+), 3 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index 5bd4205..832d773 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,9 @@
+2009-11-19  Eric Blake  <address@hidden>
+
+       build: avoid compiler warnings
+       * lib/select.c (rpl_select): Delete unused variable.
+       * lib/setsockopt.c (rpl_setsockopt): Avoid incompatible pointer.
+
 2009-11-18  Eric Blake  <address@hidden>

        nanosleep: work around cygwin bug
diff --git a/lib/select.c b/lib/select.c
index 12d3e51..e82bf88 100644
--- a/lib/select.c
+++ b/lib/select.c
@@ -322,8 +322,6 @@ rpl_select (int nfds, fd_set *rfds, fd_set *wfds, fd_set 
*xfds,
   /* Classify handles.  Create fd sets for sockets, poll the others. */
   for (i = 0; i < nfds; i++)
     {
-      WSANETWORKEVENTS ev;
-
       if ((anyfds_in[i / CHAR_BIT] & (1 << (i & (CHAR_BIT - 1)))) == 0)
        continue;

diff --git a/lib/setsockopt.c b/lib/setsockopt.c
index 96a00cc..daff382 100644
--- a/lib/setsockopt.c
+++ b/lib/setsockopt.c
@@ -41,7 +41,8 @@ rpl_setsockopt (int fd, int level, int optname, const void 
*optval, socklen_t op
     {
       const struct timeval *tv = optval;
       int milliseconds = tv->tv_sec * 1000 + tv->tv_usec / 1000;
-      r = setsockopt (sock, level, optname, &milliseconds, sizeof (int));
+      optval = &milliseconds;
+      r = setsockopt (sock, level, optname, optval, sizeof (int));
     }
   else
     {
-- 
1.6.5.rc1


From cf75ab9ee53a8942201f31bfee63f72f7f46f7bc Mon Sep 17 00:00:00 2001
From: Eric Blake <address@hidden>
Date: Wed, 18 Nov 2009 22:14:39 -0700
Subject: [PATCH 4/4] WIP: build nanosleep on mingw

---
 m4/nanosleep.m4 |    8 ++++++++
 m4/select.m4    |    1 +
 2 files changed, 9 insertions(+), 0 deletions(-)

diff --git a/m4/nanosleep.m4 b/m4/nanosleep.m4
index 211b367..3524ac0 100644
--- a/m4/nanosleep.m4
+++ b/m4/nanosleep.m4
@@ -18,6 +18,7 @@ AC_DEFUN([gl_FUNC_NANOSLEEP],

  AC_REQUIRE([gl_HEADER_TIME_H_DEFAULTS])
  AC_CHECK_HEADERS_ONCE([sys/time.h])
+ AC_REQUIRE([gl_FUNC_SELECT])

  nanosleep_save_libs=$LIBS

@@ -102,6 +103,13 @@ AC_DEFUN([gl_FUNC_NANOSLEEP],
     if test "$gl_cv_func_nanosleep" = 'no (mishandles large arguments)'; then
       AC_DEFINE([HAVE_BUG_BIG_NANOSLEEP], [1],
        [Define to 1 if nanosleep mishandles large arguments.])
+    else
+      for ac_lib in $LIBSOCKET; do
+        case " $LIB_NANOSLEEP " in
+        *" $ac_lib "*) ;;
+        *) LIB_NANOSLEEP="$LIB_NANOSLEEP $ac_lib";;
+        esac
+      done
     fi
     AC_LIBOBJ([nanosleep])
     gl_PREREQ_NANOSLEEP
diff --git a/m4/select.m4 b/m4/select.m4
index 53cc059..984ca3c 100644
--- a/m4/select.m4
+++ b/m4/select.m4
@@ -8,6 +8,7 @@ AC_DEFUN([gl_FUNC_SELECT],
 [
   AC_REQUIRE([gl_HEADER_SYS_SELECT])
   AC_REQUIRE([AC_CANONICAL_HOST]) dnl for cross-compiles
+  AC_REQUIRE([gl_SOCKETS])
   if test "$ac_cv_header_winsock2_h" = yes; then
     AC_LIBOBJ([select])
   else
-- 
1.6.5.rc1


reply via email to

[Prev in Thread] Current Thread [Next in Thread]