From: Yu Watanabe Date: Mon, 15 Dec 2025 08:50:08 +0000 (+0900) Subject: time-util: continue sleeping when clock_nanosleep() fail with EINTR X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=b8241d3ca57b7a307be1dfa39bdf3202372c1841;p=thirdparty%2Fsystemd.git 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. --- diff --git a/src/basic/time-util.c b/src/basic/time-util.c index 8c776960e1b..99915052829 100644 --- a/src/basic/time-util.c +++ b/src/basic/time-util.c @@ -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. */ diff --git a/src/basic/time-util.h b/src/basic/time-util.h index 13831fcd518..dc6427d98a8 100644 --- a/src/basic/time-util.h +++ b/src/basic/time-util.h @@ -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. */