- time_t t = ts_sleep.tv_sec + 1;
-
- /* Detect integer overflow. */
- overflow |= (t < ts_sleep.tv_sec);
-
- ts_sleep.tv_sec = t;
- ts_sleep.tv_nsec -= 1000000000;
- }
-
- /* Compute the time until which we should sleep. */
- ts_stop.tv_sec = ts_start.tv_sec + ts_sleep.tv_sec;
- ts_stop.tv_nsec = ts_start.tv_nsec + ts_sleep.tv_nsec;
- if (1000000000 <= ts_stop.tv_nsec)
- {
- ++ts_stop.tv_sec;
- ts_stop.tv_nsec -= 1000000000;
- }
-
- /* Detect integer overflow. */
- overflow |= (ts_stop.tv_sec < ts_start.tv_sec
- || (ts_stop.tv_sec == ts_start.tv_sec
- && ts_stop.tv_nsec < ts_start.tv_nsec));
-
- if (overflow)
- {
- /* Fix ts_sleep and ts_stop, which may be garbage due to overflow. */
- ts_sleep.tv_sec = ts_stop.tv_sec = TIME_T_MAX;
- ts_sleep.tv_nsec = ts_stop.tv_nsec = 999999999;
- }
-
- while (nanosleep (&ts_sleep, NULL) != 0)
- {
- if (errno != EINTR || gettime (&ts_start) != 0)
- return -1;
-
- /* POSIX.1-2001 requires that when a process is suspended, then
- resumed, nanosleep (A, B) returns -1, sets errno to EINTR,
- and sets *B to the time remaining at the point of resumption.
- However, some versions of the Linux kernel incorrectly return
- the time remaining at the point of suspension. Work around
- this bug by computing the remaining time here, rather than by
- relying on nanosleep's computation. */
-
- if (! timespec_subtract (&ts_sleep, &ts_stop, &ts_start))
- break;
+ /* Linux-2.6.8.1's nanosleep returns -1, but doesn't set errno
+ when resumed after being suspended. Earlier versions would
+ 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). */
+ errno = 0;
+ if (nanosleep (&ts_sleep, NULL) == 0)
+ break;
+ if (errno != EINTR && errno != 0)
+ return -1;