From 9b60fa3acd9b48441f8f0a2062cfd2df7ebeeb8b Mon Sep 17 00:00:00 2001
From: David Klempner <klempner@imsanet.org>
Date: Wed, 4 Feb 2015 09:48:53 -0800
Subject: [PATCH] Make gpr_timespec no longer be a typedef for struct timespec
 in posix

The problem is that for the typedef to work we need _POSIX_C_SOURCE to
be defined properly before any file that uses gpr_timespec includes
anything. This is extremely fragile unless we change CFLAGS, which
probably isn't worth doing for this.
---
 include/grpc/support/time.h       |  4 ++--
 include/grpc/support/time_posix.h |  5 ++++-
 src/core/support/sync_posix.c     | 11 ++++++++++-
 src/core/support/time_posix.c     | 25 +++++++++++++++++++++----
 4 files changed, 37 insertions(+), 8 deletions(-)

diff --git a/include/grpc/support/time.h b/include/grpc/support/time.h
index 6327a2cffb..70e4afdf6b 100644
--- a/include/grpc/support/time.h
+++ b/include/grpc/support/time.h
@@ -34,8 +34,8 @@
 #ifndef __GRPC_SUPPORT_TIME_H__
 #define __GRPC_SUPPORT_TIME_H__
 /* Time support.
-   We use gpr_timespec, which is typedefed to struct timespec on platforms which
-   have it. On some machines, absolute times may be in local time.  */
+   We use gpr_timespec, which is analogous to struct timespec.  On some
+   machines, absolute times may be in local time.  */
 
 /* Platform specific header declares gpr_timespec.
    gpr_timespec contains:
diff --git a/include/grpc/support/time_posix.h b/include/grpc/support/time_posix.h
index 9ff6f7f493..85dee5fc21 100644
--- a/include/grpc/support/time_posix.h
+++ b/include/grpc/support/time_posix.h
@@ -38,6 +38,9 @@
 #include <sys/time.h>
 #include <time.h>
 
-typedef struct timespec gpr_timespec;
+typedef struct gpr_timespec {
+    time_t tv_sec;
+    long tv_nsec;
+} gpr_timespec;
 
 #endif /* __GRPC_SUPPORT_TIME_POSIX_H__ */
diff --git a/src/core/support/sync_posix.c b/src/core/support/sync_posix.c
index 7f0e4a95a4..a28a4c6bf4 100644
--- a/src/core/support/sync_posix.c
+++ b/src/core/support/sync_posix.c
@@ -33,11 +33,17 @@
 
 /* Posix gpr synchroization support code. */
 
+#if !defined _POSIX_C_SOURCE || _POSIX_C_SOURCE < 199309L
+#undef _POSIX_C_SOURCE
+#define _POSIX_C_SOURCE 199309L
+#endif
+
 #include <grpc/support/port_platform.h>
 
 #ifdef GPR_POSIX_SYNC
 
 #include <errno.h>
+#include <time.h>
 #include <grpc/support/log.h>
 #include <grpc/support/sync.h>
 #include <grpc/support/time.h>
@@ -67,7 +73,10 @@ int gpr_cv_wait(gpr_cv *cv, gpr_mu *mu, gpr_timespec abs_deadline) {
   if (gpr_time_cmp(abs_deadline, gpr_inf_future) == 0) {
     err = pthread_cond_wait(cv, mu);
   } else {
-    err = pthread_cond_timedwait(cv, mu, &abs_deadline);
+    struct timespec abs_deadline_ts;
+    abs_deadline_ts.tv_sec = abs_deadline.tv_sec;
+    abs_deadline_ts.tv_nsec = abs_deadline.tv_nsec;
+    err = pthread_cond_timedwait(cv, mu, &abs_deadline_ts);
   }
   GPR_ASSERT(err == 0 || err == ETIMEDOUT || err == EAGAIN);
   return err == ETIMEDOUT;
diff --git a/src/core/support/time_posix.c b/src/core/support/time_posix.c
index 9e11f8a865..7f0f028183 100644
--- a/src/core/support/time_posix.c
+++ b/src/core/support/time_posix.c
@@ -34,7 +34,8 @@
 /* Posix code for gpr time support. */
 
 /* So we get nanosleep and clock_* */
-#ifndef _POSIX_C_SOURCE
+#if !defined _POSIX_C_SOURCE || _POSIX_C_SOURCE < 199309L
+#undef _POSIX_C_SOURCE
 #define _POSIX_C_SOURCE 199309L
 #endif
 
@@ -47,11 +48,25 @@
 #include <unistd.h>
 #include <grpc/support/time.h>
 
+static struct timespec timespec_from_gpr(gpr_timespec gts) {
+  struct timespec rv;
+  rv.tv_sec = gts.tv_sec;
+  rv.tv_nsec = gts.tv_nsec;
+  return rv;
+}
+
 #if _POSIX_TIMERS > 0
+static gpr_timespec gpr_from_timespec(struct timespec ts) {
+  gpr_timespec rv;
+  rv.tv_sec = ts.tv_sec;
+  rv.tv_nsec = ts.tv_nsec;
+  return rv;
+}
+
 gpr_timespec gpr_now(void) {
-  gpr_timespec now;
+  struct timespec now;
   clock_gettime(CLOCK_REALTIME, &now);
-  return now;
+  return gpr_from_timespec(now);
 }
 #else
 /* For some reason Apple's OSes haven't implemented clock_gettime. */
@@ -69,6 +84,7 @@ gpr_timespec gpr_now(void) {
 void gpr_sleep_until(gpr_timespec until) {
   gpr_timespec now;
   gpr_timespec delta;
+  struct timespec delta_ts;
 
   for (;;) {
     /* We could simplify by using clock_nanosleep instead, but it might be
@@ -79,7 +95,8 @@ void gpr_sleep_until(gpr_timespec until) {
     }
 
     delta = gpr_time_sub(until, now);
-    if (nanosleep(&delta, NULL) == 0) {
+    delta_ts = timespec_from_gpr(delta);
+    if (nanosleep(&delta_ts, NULL) == 0) {
       break;
     }
   }
-- 
GitLab