The nanoseconds part of the timespec struct time_a is not always
bigger than time_b since it wrap around each seconds.
Use 64-bit arithmetic to perform the difference.
Merge/move duplicated code into utils.c.
This function is really doing two things. Split it into timespec_to_ms()
and timespec_abs_diff().
Signed-off-by: Mathieu Desnoyers
---
Changes since v1:
- Use NSEC_PER_SEC constant.
Changes since v2:
- Move prototypes to time.h.
- Adapt timespec_to_ms() range check to take into account tv_nsec beyond
10-1.
Changes since v3:
- Use remainer for detection of overflow.
- set errno to EOVERFLOW in timespec_to_ms.
---
src/common/common.h | 1 +
src/common/sessiond-comm/inet.c | 27 +++
src/common/sessiond-comm/inet6.c | 27 +++
src/common/time.h| 15 +++
src/common/utils.c | 36
5 files changed, 66 insertions(+), 40 deletions(-)
diff --git a/src/common/common.h b/src/common/common.h
index 41eb0361..9168a245 100644
--- a/src/common/common.h
+++ b/src/common/common.h
@@ -23,5 +23,6 @@
#include "macros.h"
#include "runas.h"
#include "readwrite.h"
+#include "time.h"
#endif /* _COMMON_H */
diff --git a/src/common/sessiond-comm/inet.c b/src/common/sessiond-comm/inet.c
index e0b3e7a9..ac450dbc 100644
--- a/src/common/sessiond-comm/inet.c
+++ b/src/common/sessiond-comm/inet.c
@@ -112,31 +112,13 @@ int connect_no_timeout(struct lttcomm_sock *sock)
sizeof(sock->sockaddr.addr.sin));
}
-/*
- * Return time_a - time_b in milliseconds.
- */
-static
-unsigned long time_diff_ms(struct timespec *time_a,
- struct timespec *time_b)
-{
- time_t sec_diff;
- long nsec_diff;
- unsigned long result_ms;
-
- sec_diff = time_a->tv_sec - time_b->tv_sec;
- nsec_diff = time_a->tv_nsec - time_b->tv_nsec;
-
- result_ms = sec_diff * MSEC_PER_SEC;
- result_ms += nsec_diff / NSEC_PER_MSEC;
- return result_ms;
-}
-
static
int connect_with_timeout(struct lttcomm_sock *sock)
{
unsigned long timeout = lttcomm_get_network_timeout();
int ret, flags, connect_ret;
struct timespec orig_time, cur_time;
+ unsigned long diff_ms;
ret = fcntl(sock->fd, F_GETFL, 0);
if (ret == -1) {
@@ -217,7 +199,12 @@ int connect_with_timeout(struct lttcomm_sock *sock)
connect_ret = ret;
goto error;
}
- } while (time_diff_ms(&cur_time, &orig_time) < timeout);
+ if (timespec_to_ms(timespec_abs_diff(cur_time, orig_time),
&diff_ms) < 0) {
+ ERR("timespec_to_ms input overflows milliseconds
output");
+ connect_ret = -1;
+ goto error;
+ }
+ } while (diff_ms < timeout);
/* Timeout */
errno = ETIMEDOUT;
diff --git a/src/common/sessiond-comm/inet6.c b/src/common/sessiond-comm/inet6.c
index dfb5fc5d..03b6627d 100644
--- a/src/common/sessiond-comm/inet6.c
+++ b/src/common/sessiond-comm/inet6.c
@@ -110,31 +110,13 @@ int connect_no_timeout(struct lttcomm_sock *sock)
sizeof(sock->sockaddr.addr.sin6));
}
-/*
- * Return time_a - time_b in milliseconds.
- */
-static
-unsigned long time_diff_ms(struct timespec *time_a,
- struct timespec *time_b)
-{
- time_t sec_diff;
- long nsec_diff;
- unsigned long result_ms;
-
- sec_diff = time_a->tv_sec - time_b->tv_sec;
- nsec_diff = time_a->tv_nsec - time_b->tv_nsec;
-
- result_ms = sec_diff * MSEC_PER_SEC;
- result_ms += nsec_diff / NSEC_PER_MSEC;
- return result_ms;
-}
-
static
int connect_with_timeout(struct lttcomm_sock *sock)
{
unsigned long timeout = lttcomm_get_network_timeout();
int ret, flags, connect_ret;
struct timespec orig_time, cur_time;
+ unsigned long diff_ms;
ret = fcntl(sock->fd, F_GETFL, 0);
if (ret == -1) {
@@ -216,7 +198,12 @@ int connect_with_timeout(struct lttcomm_sock *sock)
connect_ret = ret;
goto error;
}
- } while (time_diff_ms(&cur_time, &orig_time) < timeout);
+ if (timespec_to_ms(timespec_abs_diff(cur_time, orig_time),
&diff_ms) < 0) {
+ ERR("timespec_to_ms input overflows milliseconds
output");
+ connect_ret = -1;
+ goto error;
+ }
+ } while (diff_ms < timeout);
/* Timeout */
errno = ETIMEDOUT;
diff --git a/src/common/time.h b/src/common/time.h
index 81770779..8a7dd958 100644
--- a/src/common/time.h
+++ b/src/common/time.h
@@ -19,9 +19,24 @@
#ifndef LTTNG_TIME_H
#define LTTNG_TIME_H
+#include
+
#define MSEC_PER_SEC 1000ULL
#define NSEC_PER_SEC 10ULL
#define NSEC_PER_MSEC 100ULL
#de