summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNick Mathewson <nickm@torproject.org>2016-12-21 08:17:26 -0500
committerNick Mathewson <nickm@torproject.org>2016-12-21 08:17:26 -0500
commita757f769676cf0a942fb1c909ff4cf469d362d12 (patch)
treec6fef4ffc7787e748e3745560f9e3ebd8be6b56f
parent490cd038693b89c30b60fd8682fd631f5581f458 (diff)
downloadtor-a757f769676cf0a942fb1c909ff4cf469d362d12.tar.gz
tor-a757f769676cf0a942fb1c909ff4cf469d362d12.zip
Withstand failures in CLOCK_MONOTONIC_COARSE
This came up on #21035, where somebody tried to build on a linux system with kernel headers including CLOCK_MONOTONIC_COARSE, then run on a kernel that didn't support it. I've adopted a belt-and-suspenders approach here: we detect failures at initialization time, and we also detect (loudly) failures later on. Fixes bug 21035; bugfix on 0.2.9.1-alpha when we started using monotonic time.
-rw-r--r--src/common/compat_time.c32
1 files changed, 30 insertions, 2 deletions
diff --git a/src/common/compat_time.c b/src/common/compat_time.c
index 3493ea0c22..d044bbe1d7 100644
--- a/src/common/compat_time.c
+++ b/src/common/compat_time.c
@@ -324,10 +324,27 @@ monotime_diff_nsec(const monotime_t *start,
/* end of "__APPLE__" */
#elif defined(HAVE_CLOCK_GETTIME)
+#ifdef CLOCK_MONOTONIC_COARSE
+/**
+ * Which clock should we use for coarse-grained monotonic time? By default
+ * this is CLOCK_MONOTONIC_COARSE, but it might not work -- for example,
+ * if we're compiled with newer Linux headers and then we try to run on
+ * an old Linux kernel. In that case, we will fall back to CLOCK_MONOTONIC.
+ */
+static int clock_monotonic_coarse = CLOCK_MONOTONIC_COARSE;
+#endif
+
static void
monotime_init_internal(void)
{
- /* no action needed. */
+#ifdef CLOCK_MONOTONIC_COARSE
+ struct timespec ts;
+ if (clock_gettime(CLOCK_MONOTONIC_COARSE, &ts) < 0) {
+ log_info(LD_GENERAL, "CLOCK_MONOTONIC_COARSE isn't working (%s); "
+ "falling back to CLOCK_MONOTONIC.", strerror(errno));
+ clock_monotonic_coarse = CLOCK_MONOTONIC;
+ }
+#endif
}
void
@@ -355,7 +372,18 @@ monotime_coarse_get(monotime_coarse_t *out)
return;
}
#endif
- int r = clock_gettime(CLOCK_MONOTONIC_COARSE, &out->ts_);
+ int r = clock_gettime(clock_monotonic_coarse, &out->ts_);
+ if (PREDICT_UNLIKELY(r < 0) &&
+ errno == EINVAL &&
+ clock_monotonic_coarse == CLOCK_MONOTONIC_COARSE) {
+ /* We should have caught this at startup in monotime_init_internal!
+ */
+ log_warn(LD_BUG, "Falling back to non-coarse monotonic time %s initial "
+ "system start?", monotime_initialized?"after":"without");
+ clock_monotonic_coarse = CLOCK_MONOTONIC;
+ r = clock_gettime(clock_monotonic_coarse, &out->ts_);
+ }
+
tor_assert(r == 0);
}
#endif