Fix int overflow GetClockTimeMicros() on macOS

On macOS mach_timespec_t.tv_sec is only 4 bytes and we
were converting to micros before moving to a bigger var.
This would cause all the wall times obtained on a mac (through
GetClockTimeMicros() to be wrong.

This was likely the cause of KUDU-2435 and KUDU-2408 too, since
the time would easily wrap, causing us to a update the clock with
a value that was seemingly from the future.

Posix just requires it to be an integer
(see: https://en.wikipedia.org/w/index.php?title=Time_t&oldid=450752800)
so also fixed it on the non-macOS path.

Testing this is likely not worth it since the only real change
was on macOS where the overlow doesn't happen anymore.

Change-Id: Ie0eaa548f61352be529755a732566613cfa72098
Reviewed-on: http://gerrit.cloudera.org:8080/10371
Reviewed-by: Todd Lipcon <t...@apache.org>
Reviewed-by: Dan Burkert <danburk...@apache.org>
Reviewed-by: Grant Henke <granthe...@apache.org>
Tested-by: Kudu Jenkins


Project: http://git-wip-us.apache.org/repos/asf/kudu/repo
Commit: http://git-wip-us.apache.org/repos/asf/kudu/commit/07d6b5f2
Tree: http://git-wip-us.apache.org/repos/asf/kudu/tree/07d6b5f2
Diff: http://git-wip-us.apache.org/repos/asf/kudu/diff/07d6b5f2

Branch: refs/heads/master
Commit: 07d6b5f2ba384e10288d5926af93933f0a74185d
Parents: 525943f
Author: David Alves <dral...@apache.org>
Authored: Thu May 10 13:52:14 2018 -0700
Committer: David Ribeiro Alves <davidral...@gmail.com>
Committed: Thu May 10 22:38:23 2018 +0000

----------------------------------------------------------------------
 src/kudu/gutil/walltime.h | 15 +++++++++++++--
 1 file changed, 13 insertions(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/kudu/blob/07d6b5f2/src/kudu/gutil/walltime.h
----------------------------------------------------------------------
diff --git a/src/kudu/gutil/walltime.h b/src/kudu/gutil/walltime.h
index e9cab67..4b15f42 100644
--- a/src/kudu/gutil/walltime.h
+++ b/src/kudu/gutil/walltime.h
@@ -81,7 +81,12 @@ inline void GetCurrentTime(mach_timespec_t* ts) {
 inline MicrosecondsInt64 GetCurrentTimeMicros() {
   mach_timespec_t ts;
   GetCurrentTime(&ts);
-  return ts.tv_sec * 1000000 + ts.tv_nsec / 1000;
+  // 'tv_sec' is just 4 bytes on macOS, need to be careful not
+  // to convert to nanos until we've moved to a larger int.
+  MicrosecondsInt64 micros_from_secs = ts.tv_sec;
+  micros_from_secs *= 1000 * 1000;
+  micros_from_secs += ts.tv_nsec / 1000;
+  return micros_from_secs;
 }
 
 inline int64_t GetMonoTimeNanos() {
@@ -130,7 +135,13 @@ inline MicrosecondsInt64 GetThreadCpuTimeMicros() {
 inline MicrosecondsInt64 GetClockTimeMicros(clockid_t clock) {
   timespec ts;
   clock_gettime(clock, &ts);
-  return ts.tv_sec * 1000000 + ts.tv_nsec / 1000;
+  // 'tv_sec' is usually 8 bytes, but the spec says it only
+  // needs to be 'a signed int'. Moved to a 64 bit var before
+  // converting to micros to be safe.
+  MicrosecondsInt64 micros_from_secs = ts.tv_sec;
+  micros_from_secs *= 1000 * 1000;
+  micros_from_secs += ts.tv_nsec / 1000;
+  return micros_from_secs;
 }
 
 #endif // defined(__APPLE__)

Reply via email to