time-util: continue sleeping when clock_nanosleep() fail with EINTR
The function clock_nanosleep() provides remaining time when failed with EINTR. Let's continue sleeping in that case.
This commit is contained in:
@@ -1792,6 +1792,36 @@ bool in_utc_timezone(void) {
|
||||
return timezone == 0 && daylight == 0;
|
||||
}
|
||||
|
||||
int usleep_safe(usec_t usec) {
|
||||
int r;
|
||||
|
||||
/* usleep() takes useconds_t that is (typically?) uint32_t. Also, usleep() may only support the
|
||||
* range [0, 1000000]. See usleep(3). Let's override usleep() with clock_nanosleep().
|
||||
*
|
||||
* ⚠️ Note we are not using plain nanosleep() here, since that operates on CLOCK_REALTIME, not
|
||||
* CLOCK_MONOTONIC! */
|
||||
|
||||
if (usec == 0)
|
||||
return 0;
|
||||
|
||||
struct timespec t;
|
||||
timespec_store(&t, usec);
|
||||
|
||||
for (;;) {
|
||||
struct timespec remaining;
|
||||
|
||||
/* `clock_nanosleep()` does not use `errno`, but returns positive error codes. */
|
||||
r = -clock_nanosleep(CLOCK_MONOTONIC, /* flags= */ 0, &t, &remaining);
|
||||
if (r == -EINTR) {
|
||||
/* Interrupted. Continue sleeping for the remaining time. */
|
||||
t = remaining;
|
||||
continue;
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
}
|
||||
|
||||
int time_change_fd(void) {
|
||||
|
||||
/* We only care for the cancellation event, hence we set the timeout to the latest possible value. */
|
||||
|
||||
+1
-13
@@ -213,19 +213,7 @@ static inline usec_t usec_sub_signed(usec_t timestamp, int64_t delta) {
|
||||
return usec_sub_unsigned(timestamp, (usec_t) delta);
|
||||
}
|
||||
|
||||
static inline int usleep_safe(usec_t usec) {
|
||||
/* usleep() takes useconds_t that is (typically?) uint32_t. Also, usleep() may only support the
|
||||
* range [0, 1000000]. See usleep(3). Let's override usleep() with clock_nanosleep().
|
||||
*
|
||||
* ⚠️ Note we are not using plain nanosleep() here, since that operates on CLOCK_REALTIME, not
|
||||
* CLOCK_MONOTONIC! */
|
||||
|
||||
if (usec == 0)
|
||||
return 0;
|
||||
|
||||
/* `clock_nanosleep()` does not use `errno`, but returns positive error codes. */
|
||||
return -clock_nanosleep(CLOCK_MONOTONIC, 0, TIMESPEC_STORE(usec), NULL);
|
||||
}
|
||||
int usleep_safe(usec_t usec);
|
||||
|
||||
/* The last second we can format is 31. Dec 9999, 1s before midnight, because otherwise we'd enter 5 digit
|
||||
* year territory. However, since we want to stay away from this in all timezones we take one day off. */
|
||||
|
||||
Reference in New Issue
Block a user