HEX
Server: Apache
System: Linux scp1.abinfocom.com 5.4.0-216-generic #236-Ubuntu SMP Fri Apr 11 19:53:21 UTC 2025 x86_64
User: confeduphaar (1010)
PHP: 8.1.33
Disabled: exec,passthru,shell_exec,system
Upload Files
File: //usr/src/glibc/debian/patches/ubuntu/local-fallback-to-monotonic.diff
From 01849fca6c83afa9e7c60a9f1031760f3e283b52 Mon Sep 17 00:00:00 2001
From: Balint Reczey <balint.reczey@canonical.com>
Date: Mon, 27 Jul 2020 18:44:40 +0200
Subject: [PATCH] Fall back to CLOCK_MONOTONIC when clock_nanosleep_time64 with
 CLOCK_REALTIME fails

Based on Christian Pfeiffer's patch at
https://gist.github.com/ChrisTX/391fe201b3d72d3b3dac17066100347d

See: https://github.com/microsoft/WSL/issues/4898
---
 sysdeps/unix/sysv/linux/clock_nanosleep.c | 38 +++++++++++++++++++++++
 1 file changed, 38 insertions(+)

diff --git a/sysdeps/unix/sysv/linux/clock_nanosleep.c b/sysdeps/unix/sysv/linux/clock_nanosleep.c
index 728137aa56..99c5671ff4 100644
--- a/sysdeps/unix/sysv/linux/clock_nanosleep.c
+++ b/sysdeps/unix/sysv/linux/clock_nanosleep.c
@@ -24,6 +24,36 @@
 
 #include <shlib-compat.h>
 
+
+static int valid_nanosleep_ts (const struct __timespec64 *ts) {
+  return (ts->tv_nsec >= 0 && ts->tv_nsec < 1000000000L && ts->tv_sec >= 0);
+}
+
+/* Use CLOCK_MONOTONIC and convert request with TIMER_ABSTIME to use relative time */
+#define MONOTONIC_FALLBACK do {                                         \
+    if (__glibc_unlikely (flags & TIMER_ABSTIME))                       \
+    {                                                                   \
+      struct __timespec64 current_realtime, actual_req;                 \
+      actual_req = *req;                                                \
+      if(__clock_gettime64(CLOCK_REALTIME, &current_realtime))          \
+        return EINVAL;                                                  \
+      actual_req.tv_nsec -= current_realtime.tv_nsec;                   \
+      actual_req.tv_sec -= current_realtime.tv_sec;                     \
+      if (actual_req.tv_nsec < 0)                                       \
+      {                                                                 \
+        --actual_req.tv_sec;                                            \
+        actual_req.tv_nsec = 1000000000L + actual_req.tv_nsec;          \
+      }                                                                 \
+      r = INTERNAL_SYSCALL_CANCEL (clock_nanosleep_time64,              \
+                                   err, CLOCK_MONOTONIC,                \
+                                   flags & ~TIMER_ABSTIME,              \
+                                   &actual_req, rem);                   \
+    } else                                                              \
+      r = INTERNAL_SYSCALL_CANCEL (clock_nanosleep_time64,              \
+                                   err, CLOCK_MONOTONIC, flags,         \
+                                   req, rem);                           \
+  } while (0)
+
 /* We can simply use the syscall.  The CPU clocks are not supported
    with this function.  */
 int
@@ -47,10 +77,18 @@ __clock_nanosleep_time64 (clockid_t clock_id, int flags, const struct __timespec
 # endif
   r = INTERNAL_SYSCALL_CANCEL (clock_nanosleep_time64, err, clock_id,
                                flags, req, rem);
+  if (__glibc_unlikely (INTERNAL_SYSCALL_ERRNO (r, err) == EINVAL
+                        && clock_id == CLOCK_REALTIME
+                        && valid_nanosleep_ts(req)))
+    MONOTONIC_FALLBACK;
 #else
 # ifdef __NR_clock_nanosleep_time64
   r = INTERNAL_SYSCALL_CANCEL (clock_nanosleep_time64, err, clock_id,
                                flags, req, rem);
+  if (__glibc_unlikely (INTERNAL_SYSCALL_ERRNO (r, err) == EINVAL
+                        && clock_id == CLOCK_REALTIME
+                        && valid_nanosleep_ts(req)))
+    MONOTONIC_FALLBACK;
 
   if (! INTERNAL_SYSCALL_ERROR_P (r, err))
     return 0;
-- 
2.25.1