]> git.ipfire.org Git - thirdparty/glibc.git/commitdiff
Y2038: add function __sigtimedwait_time64
authorAlbert ARIBAUD (3ADEV) <albert.aribaud@3adev.fr>
Thu, 7 Sep 2017 22:41:41 +0000 (00:41 +0200)
committerAlbert ARIBAUD (3ADEV) <albert.aribaud@3adev.fr>
Wed, 24 Oct 2018 10:53:27 +0000 (12:53 +0200)
signal/sigtimedwait.c
sysdeps/unix/sysv/linux/sigtimedwait.c
time/Versions

index 308b9b95d7b9596ccd12163b05a33e10d07c9777..e187883bcc46fab2b03d5d6d0d598c5a55c62224 100644 (file)
@@ -30,3 +30,13 @@ libc_hidden_def (__sigtimedwait)
 weak_alias (__sigtimedwait, sigtimedwait)
 
 stub_warning (sigtimedwait)
+
+int
+__sigtimedwait_time64 (const sigset_t *set, siginfo_t *info,
+               const struct __timespec64 *timeout)
+{
+  __set_errno (ENOSYS);
+  return -1;
+}
+
+stub_warning (__sigtimedwait_time64)
index b4de8856dd8625a68e74bc28ba06cd55042c5b3e..6cfe8f082e03235bacc2a8ebaa804f865bd1332c 100644 (file)
 #include <errno.h>
 #include <signal.h>
 #include <string.h>
+//#include <stdint.h>
+
+//#include <nptl/pthreadP.h>
 #include <sysdep-cancel.h>
+#include <y2038-support.h>
 
 int
 __sigtimedwait (const sigset_t *set, siginfo_t *info,
@@ -39,3 +43,80 @@ __sigtimedwait (const sigset_t *set, siginfo_t *info,
 }
 libc_hidden_def (__sigtimedwait)
 weak_alias (__sigtimedwait, sigtimedwait)
+
+/* 64-bit time version */
+
+int
+__sigtimedwait_time64 (const sigset_t *set, siginfo_t *info,
+               const struct __timespec64 *timeout)
+{
+  int result;
+  struct timespec ts32;
+#ifdef __NR_rt_sigtimedwait_time64
+  struct __timespec64 ts64;
+#endif
+
+#ifdef SIGCANCEL
+  sigset_t tmpset;
+  if (set != NULL
+      && (__builtin_expect (__sigismember (set, SIGCANCEL), 0)
+# ifdef SIGSETXID
+         || __builtin_expect (__sigismember (set, SIGSETXID), 0)
+# endif
+         ))
+    {
+      /* Create a temporary mask without the bit for SIGCANCEL set.  */
+      // We are not copying more than we have to.
+      memcpy (&tmpset, set, _NSIG / 8);
+      __sigdelset (&tmpset, SIGCANCEL);
+# ifdef SIGSETXID
+      __sigdelset (&tmpset, SIGSETXID);
+# endif
+      set = &tmpset;
+    }
+#endif
+
+    /* XXX The size argument hopefully will have to be changed to the
+       real size of the user-level sigset_t.  */
+#ifdef __NR_rt_sigtimedwait_time64
+  if (__y2038_linux_support > 0)
+    {
+      if (timeout)
+        {
+          ts64.tv_sec = timeout->tv_sec;
+          ts64.tv_nsec = timeout->tv_nsec;
+          ts64.tv_pad = 0;
+          result = SYSCALL_CANCEL (rt_sigtimedwait_time64, set, info, &ts64, _NSIG / 8);
+          if (result == -1 && errno==ENOSYS)
+           {
+             __y2038_linux_support = -1;
+           }
+        }
+      else
+        result = SYSCALL_CANCEL (rt_sigtimedwait, set, info, NULL, _NSIG / 8);
+    }
+  else
+#endif
+    {
+      if (timeout)
+        {
+          if (! timespec64_to_timespec(timeout, &ts32))
+            {
+              errno = EOVERFLOW;
+              return -1;
+            }
+          result = SYSCALL_CANCEL (rt_sigtimedwait, set, info, &ts32, _NSIG / 8);
+        }
+      else
+        result = SYSCALL_CANCEL (rt_sigtimedwait, set, info, NULL, _NSIG / 8);
+    }
+
+  /* The kernel generates a SI_TKILL code in si_code in case tkill is
+     used.  tkill is transparently used in raise().  Since having
+     SI_TKILL as a code is useful in general we fold the results
+     here.  */
+  if (result != -1 && info != NULL && info->si_code == SI_TKILL)
+    info->si_code = SI_USER;
+
+  return result;
+}
index 5614729fc5705a129ae7243d6e1234c04c1a899f..8e5f02189b820aabc5c45295b176070832fc2187 100644 (file)
@@ -77,5 +77,6 @@ libc {
     __timespec_get64;
     __utimensat_time64;
     __futimens64;
+    __sigtimedwait_time64;
   }
 }