Repository : ssh://git@open-mesh.org/alfred
On branch : master
commit c333a27dbd13d262949d7252681750ca0b06e270 Author: Sven Eckelmann sven@open-mesh.com Date: Wed Jan 16 16:17:56 2013 +0100
alfred: Guarantee monotonic times
The times returned by time(..) and gettimeofday(...) are not monotonic and therefore the time can jump backwards or forwards. This can happen during after a settime system call or when the local timezone was changed.
Jumps forward are not problematic and only cause early processing of some data/more data in the network, but warping back in time can result in hangs and publishing of outdated data.
Signed-off-by: Sven Eckelmann sven@open-mesh.com
c333a27dbd13d262949d7252681750ca0b06e270 Makefile | 2 +- alfred.h | 8 ++++---- recv.c | 4 ++-- server.c | 22 ++++++++++++---------- unix_sock.c | 11 ++++++----- util.c | 10 +++++----- 6 files changed, 30 insertions(+), 27 deletions(-)
diff --git a/Makefile b/Makefile index 67ff185..159aff2 100644 --- a/Makefile +++ b/Makefile @@ -24,7 +24,7 @@ OBJ = main.o server.o client.o netsock.o send.o recv.o hash.o unix_sock.o util.o
# alfred flags and options CFLAGS += -pedantic -Wall -W -std=gnu99 -fno-strict-aliasing -MD -LDLIBS += +LDLIBS += -lrt
# disable verbose output ifneq ($(findstring $(MAKEFLAGS),s),s) diff --git a/alfred.h b/alfred.h index bab2049..6a7045b 100644 --- a/alfred.h +++ b/alfred.h @@ -48,7 +48,7 @@ struct dataset { struct alfred_data data; unsigned char *buf;
- time_t last_seen; + struct timespec last_seen; enum data_source data_source; uint8_t local_data; }; @@ -56,7 +56,7 @@ struct dataset { struct server { struct ether_addr hwaddr; struct in6_addr address; - time_t last_seen; + struct timespec last_seen; uint8_t tq; };
@@ -125,7 +125,7 @@ int vis_update_data(struct globals *globals); int netsock_open(struct globals *globals); int netsock_close(int sock); /* util.c */ -int time_diff(struct timeval *tv1, struct timeval *tv2, - struct timeval *tvdiff); +int time_diff(struct timespec *tv1, struct timespec *tv2, + struct timespec *tvdiff); void time_random_seed(void); uint16_t get_random_id(void); diff --git a/recv.c b/recv.c index f7be8f3..fd25f46 100644 --- a/recv.c +++ b/recv.c @@ -79,7 +79,7 @@ static int process_alfred_push_data(struct globals *globals, if (dataset->data_source == SOURCE_LOCAL) goto skip_data;
- dataset->last_seen = time(NULL); + clock_gettime(CLOCK_MONOTONIC, &dataset->last_seen);
/* free old buffer */ if (dataset->buf) @@ -146,7 +146,7 @@ process_alfred_announce_master(struct globals *globals, } }
- server->last_seen = time(NULL); + clock_gettime(CLOCK_MONOTONIC, &server->last_seen); if (strcmp(globals->mesh_iface, "none") != 0) { macaddr = translate_mac(globals->mesh_iface, (struct ether_addr *)&server->hwaddr); diff --git a/server.c b/server.c index fd0d282..acd8a9c 100644 --- a/server.c +++ b/server.c @@ -120,14 +120,15 @@ int set_best_server(struct globals *globals) static int purge_data(struct globals *globals) { struct hash_it_t *hashit = NULL; - time_t now; + struct timespec now, diff;
- now = time(NULL); + clock_gettime(CLOCK_MONOTONIC, &now);
while (NULL != (hashit = hash_iterate(globals->data_hash, hashit))) { struct dataset *dataset = hashit->bucket->data;
- if (dataset->last_seen + ALFRED_DATA_TIMEOUT >= now) + time_diff(&now, &dataset->last_seen, &diff); + if (diff.tv_sec < ALFRED_DATA_TIMEOUT) continue;
hash_remove_bucket(globals->data_hash, hashit); @@ -138,7 +139,8 @@ static int purge_data(struct globals *globals) while (NULL != (hashit = hash_iterate(globals->server_hash, hashit))) { struct server *server = hashit->bucket->data;
- if (server->last_seen + ALFRED_SERVER_TIMEOUT >= now) + time_diff(&now, &server->last_seen, &diff); + if (diff.tv_sec < ALFRED_SERVER_TIMEOUT) continue;
if (globals->best_server == server) @@ -157,7 +159,7 @@ static int purge_data(struct globals *globals) int alfred_server(struct globals *globals) { int maxsock, ret; - struct timeval tv, last_check, now; + struct timespec last_check, now, tv; fd_set fds;
if (create_hashes(globals)) @@ -182,20 +184,20 @@ int alfred_server(struct globals *globals) if (globals->unix_sock > maxsock) maxsock = globals->unix_sock;
- gettimeofday(&last_check, NULL); + clock_gettime(CLOCK_MONOTONIC, &last_check);
while (1) { - gettimeofday(&now, NULL); + clock_gettime(CLOCK_MONOTONIC, &now); now.tv_sec -= ALFRED_INTERVAL; if (!time_diff(&last_check, &now, &tv)) { tv.tv_sec = 0; - tv.tv_usec = 0; + tv.tv_nsec = 0; }
FD_ZERO(&fds); FD_SET(globals->unix_sock, &fds); FD_SET(globals->netsock, &fds); - ret = select(maxsock + 1, &fds, NULL, NULL, &tv); + ret = pselect(maxsock + 1, &fds, NULL, NULL, &tv, NULL);
if (ret == -1) { fprintf(stderr, "main loop select failed ...: %s\n", @@ -210,7 +212,7 @@ int alfred_server(struct globals *globals) continue; } } - gettimeofday(&last_check, NULL); + clock_gettime(CLOCK_MONOTONIC, &last_check);
if (globals->opmode == OPMODE_MASTER) { /* we are a master */ diff --git a/unix_sock.c b/unix_sock.c index 037761e..b4b05cd 100644 --- a/unix_sock.c +++ b/unix_sock.c @@ -130,7 +130,7 @@ static int unix_sock_add_data(struct globals *globals, } } dataset->data_source = SOURCE_LOCAL; - dataset->last_seen = time(NULL); + clock_gettime(CLOCK_MONOTONIC, &dataset->last_seen);
/* free old buffer */ free(dataset->buf); @@ -152,7 +152,7 @@ static int unix_sock_req_data(struct globals *globals, int client_sock) { struct hash_it_t *hashit = NULL; - struct timeval tv, last_check, now; + struct timespec tv, last_check, now; fd_set fds; int ret, len; uint8_t buf[MAX_PAYLOAD]; @@ -177,17 +177,18 @@ static int unix_sock_req_data(struct globals *globals,
/* process incoming packets ... */ FD_ZERO(&fds); - gettimeofday(&last_check, NULL); + clock_gettime(CLOCK_MONOTONIC, &last_check);
while (1) { - gettimeofday(&now, NULL); + clock_gettime(CLOCK_MONOTONIC, &now); now.tv_sec -= ALFRED_REQUEST_TIMEOUT; if (!time_diff(&last_check, &now, &tv)) break;
FD_SET(globals->netsock, &fds);
- ret = select(globals->netsock + 1, &fds, NULL, NULL, &tv); + ret = pselect(globals->netsock + 1, &fds, NULL, NULL, &tv, + NULL);
if (ret == -1) { fprintf(stderr, "select failed ...: %s\n", diff --git a/util.c b/util.c index ffb7aca..5405c84 100644 --- a/util.c +++ b/util.c @@ -24,14 +24,14 @@ #include <stdint.h> #include <stdlib.h>
-int time_diff(struct timeval *tv1, struct timeval *tv2, - struct timeval *tvdiff) { +int time_diff(struct timespec *tv1, struct timespec *tv2, + struct timespec *tvdiff) { tvdiff->tv_sec = tv1->tv_sec - tv2->tv_sec; - if (tv1->tv_usec < tv2->tv_usec) { - tvdiff->tv_usec = 1000000 + tv1->tv_usec - tv2->tv_usec; + if (tv1->tv_nsec < tv2->tv_nsec) { + tvdiff->tv_nsec = 1000000000 + tv1->tv_nsec - tv2->tv_nsec; tvdiff->tv_sec -= 1; } else { - tvdiff->tv_usec = tv1->tv_usec - tv2->tv_usec; + tvdiff->tv_nsec = tv1->tv_nsec - tv2->tv_nsec; }
return (tvdiff->tv_sec >= 0);