diff options
author | Nick Mathewson <nickm@torproject.org> | 2016-12-21 08:17:26 -0500 |
---|---|---|
committer | Nick Mathewson <nickm@torproject.org> | 2016-12-21 08:17:26 -0500 |
commit | a757f769676cf0a942fb1c909ff4cf469d362d12 (patch) | |
tree | c6fef4ffc7787e748e3745560f9e3ebd8be6b56f | |
parent | 490cd038693b89c30b60fd8682fd631f5581f458 (diff) | |
download | tor-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.c | 32 |
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 |