[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
sleep, nanosleep test failures
From: |
Bruno Haible |
Subject: |
sleep, nanosleep test failures |
Date: |
Fri, 12 Nov 2010 11:57:39 +0100 |
User-agent: |
KMail/1.9.9 |
Hi,
On a stock Linux/x86 machine I observe these test failures:
test-nanosleep.c:78: assertion failed
FAIL: test-nanosleep
test-sleep.c:53: assertion failed
FAIL: test-sleep
It's a "Red Hat Enterprise Linux ES release 4 (Nahant Update 8)" machine
with Linux 2.6.9 kernel and glibc 2.3.4.
The reason is that when sleep() is asked to sleep for 49 days and interrupted
after 1 second, it returns an "unslept amount" of 24.85 days. This is similar
to the Cygwin 1.5.x behaviour, for which we already have a workaround.
ltrace execution:
signal(14, 0x8048740) = NULL
alarm(1) = 0
sleep(4233600 <unfinished ...>
--- SIGALRM (Alarm clock) ---
<... sleep resumed> ) = 2147156
strace execution:
rt_sigaction(SIGALRM, {0x8048740, [ALRM], SA_RESTORER|SA_RESTART, 0x5ee9b8},
{SIG_DFL}, 8) = 0
alarm(1) = 0
rt_sigprocmask(SIG_BLOCK, [CHLD], [], 8) = 0
rt_sigaction(SIGCHLD, NULL, {SIG_DFL}, 8) = 0
rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
nanosleep({4233600, 0}, 0xbfe8a254) = ? ERESTART_RESTARTBLOCK (To be
restarted)
--- SIGALRM (Alarm clock) @ 0 (0) ---
sigreturn() = ? (mask now [])
Looking at the implementation of sleep() in glibc, the bug must be really in
the kernel.
Jim, is this OK to commit? It fixes the issue.
2010-11-12 Bruno Haible <address@hidden>
sleep, nanosleep: Work around Linux 2.6.9 nanosleep bug.
* lib/sleep.c (rpl_sleep): Split in chunks no larger than 24 days.
* lib/nanosleep.c (nanosleep): Likewise.
--- lib/sleep.c.orig Fri Nov 12 11:45:59 2010
+++ lib/sleep.c Fri Nov 12 11:34:07 2010
@@ -1,5 +1,5 @@
/* Pausing execution of the current thread.
- Copyright (C) 2007, 2009, 2010 Free Software Foundation, Inc.
+ Copyright (C) 2007, 2009-2010 Free Software Foundation, Inc.
Written by Bruno Haible <address@hidden>, 2007.
This program is free software: you can redistribute it and/or modify
@@ -50,13 +50,14 @@
/* 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. */
+ garbage answer. Similarly, Linux 2.6.9 with glibc 2.3.4 has a too
+ small return value when asked to sleep more than 24.85 days. */
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;
+ verify (UINT_MAX / 24 / 24 / 60 / 60);
+ const unsigned int limit = 24 * 24 * 60 * 60;
while (limit < seconds)
{
unsigned int result;
--- lib/nanosleep.c.orig Fri Nov 12 11:45:59 2010
+++ lib/nanosleep.c Fri Nov 12 11:36:49 2010
@@ -47,10 +47,11 @@
struct timespec *remaining_delay)
#undef nanosleep
{
- /* nanosleep mishandles large sleeps due to internal overflow
- 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. */
+ /* nanosleep mishandles large sleeps due to internal overflow problems.
+ The worst known case of this is Linux 2.6.9 with glibc 2.3.4, which
+ can't sleep more than 24.85 days (2^31 milliseconds). Similarly,
+ 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. */
if (requested_delay->tv_nsec < 0 || BILLION <= requested_delay->tv_nsec)
{
@@ -60,8 +61,8 @@
{
/* Verify that time_t is large enough. */
- verify (TYPE_MAXIMUM (time_t) / 49 / 24 / 60 / 60);
- const time_t limit = 49 * 24 * 60 * 60;
+ verify (TYPE_MAXIMUM (time_t) / 24 / 24 / 60 / 60);
+ const time_t limit = 24 * 24 * 60 * 60;
time_t seconds = requested_delay->tv_sec;
struct timespec intermediate;
intermediate.tv_nsec = 0;
- sleep, nanosleep test failures,
Bruno Haible <=