diff options
author | Markos Fountoulakis <44345837+mfundul@users.noreply.github.com> | 2019-02-18 18:29:29 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2019-02-18 18:29:29 +0200 |
commit | e0d6a2f5fac251479c99463d70e65d9674a50796 (patch) | |
tree | d876f29eb409bb104fb21d5f4ce4fb8fcfcd0d22 | |
parent | 2881c3e5a181d65a95d3f3d68d22bfe2f5c62a1d (diff) |
When running a binary with CLOCK_BOOTTIME defined on a system with a linux (#5415)
kernel older than Linux 2.6.39 the clock_gettime(2) system call fails with
EINVAL. In that case it must fall-back to CLOCK_MONOTONIC.
-rw-r--r-- | daemon/main.c | 1 | ||||
-rw-r--r-- | libnetdata/clocks/clocks.c | 14 | ||||
-rw-r--r-- | libnetdata/clocks/clocks.h | 6 |
3 files changed, 18 insertions, 3 deletions
diff --git a/daemon/main.c b/daemon/main.c index 3d923e1217..e93e97caac 100644 --- a/daemon/main.c +++ b/daemon/main.c @@ -955,6 +955,7 @@ int main(int argc, char **argv) { if(i > 0) mallopt(M_ARENA_MAX, 1); #endif + test_clock_boottime(); // prepare configuration environment variables for the plugins diff --git a/libnetdata/clocks/clocks.c b/libnetdata/clocks/clocks.c index f303ccddcb..f7d2171780 100644 --- a/libnetdata/clocks/clocks.c +++ b/libnetdata/clocks/clocks.c @@ -2,6 +2,8 @@ #include "../libnetdata.h" +static int clock_boottime_valid = 1; + #ifndef HAVE_CLOCK_GETTIME inline int clock_gettime(clockid_t clk_id, struct timespec *ts) { struct timeval tv; @@ -15,6 +17,12 @@ inline int clock_gettime(clockid_t clk_id, struct timespec *ts) { } #endif +void test_clock_boottime(void) { + struct timespec ts; + if(clock_gettime(CLOCK_BOOTTIME, &ts) == -1 && errno == EINVAL) + clock_boottime_valid = 0; +} + static inline time_t now_sec(clockid_t clk_id) { struct timespec ts; if(unlikely(clock_gettime(clk_id, &ts) == -1)) { @@ -73,15 +81,15 @@ inline int now_monotonic_timeval(struct timeval *tv) { } inline time_t now_boottime_sec(void) { - return now_sec(CLOCK_BOOTTIME); + return now_sec(likely(clock_boottime_valid) ? CLOCK_BOOTTIME : CLOCK_MONOTONIC); } inline usec_t now_boottime_usec(void) { - return now_usec(CLOCK_BOOTTIME); + return now_usec(likely(clock_boottime_valid) ? CLOCK_BOOTTIME : CLOCK_MONOTONIC); } inline int now_boottime_timeval(struct timeval *tv) { - return now_timeval(CLOCK_BOOTTIME, tv); + return now_timeval(likely(clock_boottime_valid) ? CLOCK_BOOTTIME : CLOCK_MONOTONIC, tv); } inline usec_t timeval_usec(struct timeval *tv) { diff --git a/libnetdata/clocks/clocks.h b/libnetdata/clocks/clocks.h index d576d86b98..47aa148c12 100644 --- a/libnetdata/clocks/clocks.h +++ b/libnetdata/clocks/clocks.h @@ -130,4 +130,10 @@ extern usec_t heartbeat_monotonic_dt_to_now_usec(heartbeat_t *hb); extern int sleep_usec(usec_t usec); +/* + * When running a binary with CLOCK_BOOTTIME defined on a system with a linux kernel older than Linux 2.6.39 the + * clock_gettime(2) system call fails with EINVAL. In that case it must fall-back to CLOCK_MONOTONIC. + */ +void test_clock_boottime(void); + #endif /* NETDATA_CLOCKS_H */ |