]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
time-util: continue sleeping when clock_nanosleep() fail with EINTR
authorYu Watanabe <watanabe.yu+github@gmail.com>
Mon, 15 Dec 2025 08:50:08 +0000 (17:50 +0900)
committerYu Watanabe <watanabe.yu+github@gmail.com>
Mon, 15 Dec 2025 08:50:19 +0000 (17:50 +0900)
The function clock_nanosleep() provides remaining time when failed with
EINTR. Let's continue sleeping in that case.

src/basic/time-util.c
src/basic/time-util.h

index 8c776960e1bba4339c2b3ef0269b0ece765dd672..999150528293673b650db2ffee103476f8221d4c 100644 (file)
@@ -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. */
index 13831fcd5185fbc029fbf5c128b467743d289608..dc6427d98a8819168807fc332ada0a3c6cafa071 100644 (file)
@@ -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. */