gluon-neighbour-info: simplify and fix timeout calculation

The timeout was calculated incorrectly (in each iteration the span between
the start time and the current time was substracted from the timeout
again), and would often become negative, causing warnings in the kernel
log.
This commit is contained in:
Matthias Schiffer 2015-12-13 19:08:37 +01:00
parent a3155c427a
commit fa504dae8d

View File

@ -58,7 +58,7 @@ void getclock(struct timeval *tv) {
} }
/* Assumes a and b are normalized */ /* Assumes a and b are normalized */
void tv_subtract (struct timeval *r, struct timeval *a, struct timeval *b) { void tv_subtract (struct timeval *r, const struct timeval *a, const struct timeval *b) {
r->tv_usec = a->tv_usec - b->tv_usec; r->tv_usec = a->tv_usec - b->tv_usec;
r->tv_sec = a->tv_sec - b->tv_sec; r->tv_sec = a->tv_sec - b->tv_sec;
@ -68,18 +68,17 @@ void tv_subtract (struct timeval *r, struct timeval *a, struct timeval *b) {
} }
} }
ssize_t recvtimeout(int socket, void *buffer, size_t length, int flags, struct timeval *timeout, struct timeval *offset) { ssize_t recvtimeout(int socket, void *buffer, size_t length, int flags, const struct timeval *timeout) {
struct timeval now, delta; struct timeval now, timeout_left;
ssize_t ret;
setsockopt(socket, SOL_SOCKET, SO_RCVTIMEO, timeout, sizeof(*timeout));
ret = recv(socket, buffer, length, flags);
getclock(&now); getclock(&now);
tv_subtract(&delta, &now, offset); tv_subtract(&timeout_left, timeout, &now);
tv_subtract(timeout, timeout, &delta);
return ret; if (timeout_left.tv_sec < 0)
return -1;
setsockopt(socket, SOL_SOCKET, SO_RCVTIMEO, &timeout_left, sizeof(timeout_left));
return recv(socket, buffer, length, flags);
} }
int request(const int sock, const struct sockaddr_in6 *client_addr, const char *request, const char *sse, double timeout, unsigned int max_count) { int request(const int sock, const struct sockaddr_in6 *client_addr, const char *request, const char *sse, double timeout, unsigned int max_count) {
@ -94,14 +93,18 @@ int request(const int sock, const struct sockaddr_in6 *client_addr, const char *
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
struct timeval tv_timeout, tv_offset; struct timeval tv_timeout;
tv_timeout.tv_sec = (int) timeout; getclock(&tv_timeout);
tv_timeout.tv_usec = ((int) (timeout * 1000000)) % 1000000;
getclock(&tv_offset); tv_timeout.tv_sec += (int) timeout;
tv_timeout.tv_usec += ((int) (timeout * 1000000)) % 1000000;
if (tv_timeout.tv_usec >= 1000000) {
tv_timeout.tv_usec -= 1000000;
tv_timeout.tv_sec += 1;
}
do { do {
ret = recvtimeout(sock, buffer, sizeof(buffer), 0, &tv_timeout, &tv_offset); ret = recvtimeout(sock, buffer, sizeof(buffer), 0, &tv_timeout);
if (ret < 0) if (ret < 0)
break; break;
@ -176,6 +179,10 @@ int main(int argc, char **argv) {
break; break;
case 't': case 't':
timeout = atof(optarg); timeout = atof(optarg);
if (timeout < 0) {
perror("Negative timeout not supported");
exit(EXIT_FAILURE);
}
break; break;
case 's': case 's':
sse = optarg; sse = optarg;