On mingw, there is a 'nanosleep' function in libwinpthread. On 32-bit mingw, it does not fail when the tv_nsec argument is negative. This is currently not being caught at configure time, and causes the 'test-nanosleep' test to hang (more precisely, to hang for 1000 seconds).
This patch - adds a faster unit test, that fails within 1 second instead of 1000 seconds, - adds a workaround. 2022-09-03 Bruno Haible <br...@clisp.org> nanosleep: Work around bug on newer 32-bit mingw. * m4/nanosleep.m4 (gl_FUNC_NANOSLEEP): Test for 32-bit mingw bug. * tests/test-nanosleep.c (main): Add another test. * doc/posix-functions/nanosleep.texi: Mention the mingw bug. diff --git a/m4/nanosleep.m4 b/m4/nanosleep.m4 index 1964b1ea47..dfe21f56d5 100644 --- a/m4/nanosleep.m4 +++ b/m4/nanosleep.m4 @@ -1,4 +1,4 @@ -# serial 41 +# serial 42 dnl From Jim Meyering. dnl Check for the nanosleep function. @@ -100,15 +100,22 @@ AC_DEFUN([gl_FUNC_NANOSLEEP], #else /* A simpler test for native Windows. */ if (nanosleep (&ts_sleep, &ts_remaining) < 0) return 3; + /* Test for 32-bit mingw bug: negative nanosecond values do not + cause failure. */ + ts_sleep.tv_sec = 1; + ts_sleep.tv_nsec = -1; + if (nanosleep (&ts_sleep, &ts_remaining) != -1) + return 7; #endif return 0; }]])], [gl_cv_func_nanosleep=yes], - [case $? in dnl ( - 4|5|6) gl_cv_func_nanosleep='no (mishandles large arguments)';; dnl ( - *) gl_cv_func_nanosleep=no;; + [case $? in + 4|5|6) gl_cv_func_nanosleep='no (mishandles large arguments)' ;; + 7) gl_cv_func_nanosleep='no (mishandles negative tv_nsec)' ;; + *) gl_cv_func_nanosleep=no ;; esac], - [case "$host_os" in dnl (( + [case "$host_os" in linux*) # Guess it halfway works when the kernel is Linux. gl_cv_func_nanosleep='guessing no (mishandles large arguments)' ;; mingw*) # Guess no on native Windows. diff --git a/tests/test-nanosleep.c b/tests/test-nanosleep.c index e7edeffc0e..c208161559 100644 --- a/tests/test-nanosleep.c +++ b/tests/test-nanosleep.c @@ -43,16 +43,27 @@ main (void) { struct timespec ts; + /* Check that negative nanosecond values cause failure. */ + ts.tv_sec = 1; + ts.tv_nsec = -1; + errno = 0; + ASSERT (nanosleep (&ts, NULL) == -1); + ASSERT (errno == EINVAL); + ts.tv_sec = 1000; ts.tv_nsec = -1; errno = 0; ASSERT (nanosleep (&ts, NULL) == -1); ASSERT (errno == EINVAL); + + /* Check that too large nanosecond values cause failure. */ + ts.tv_sec = 1000; ts.tv_nsec = 1000000000; errno = 0; ASSERT (nanosleep (&ts, NULL) == -1); ASSERT (errno == EINVAL); + /* Check successful call. */ ts.tv_sec = 0; ts.tv_nsec = 1; ASSERT (nanosleep (&ts, &ts) == 0); diff --git a/doc/posix-functions/nanosleep.texi b/doc/posix-functions/nanosleep.texi index 8ede0b01f9..be54aef571 100644 --- a/doc/posix-functions/nanosleep.texi +++ b/doc/posix-functions/nanosleep.texi @@ -18,6 +18,10 @@ Linux 64-bit, Solaris 64-bit. @item This function cannot sleep longer than 49.7 days on some platforms: Cygwin 1.5.x. +@item +This function does not fail when passed a negative nanosecond value on some +platforms: +newer 32-bit mingw. @end itemize Portability problems not fixed by Gnulib: