Fix various timer-related issues
Changes: * Replace usage of gettimeofday() with clock_gettime() in the main event loop, patty_ax25_server_run(), as gettimeofday() apparently goes backwards in time occasionally, as per: https://bugzilla.redhat.com/show_bug.cgi?id=174390 Thanks Iain MM0ROR! * Fix patty_timer_expired() to properly return true if the remaining number of seconds is zero, but the remaining higher precision time is less than zero * Implement patty_timer_sub() to subtract two struct timespec values, as glibc lacks timespecsub()
This commit is contained in:
parent
f54db37a7e
commit
3e51b48453
3 changed files with 38 additions and 19 deletions
|
@ -9,7 +9,7 @@ enum patty_timer_flags {
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct _patty_timer {
|
typedef struct _patty_timer {
|
||||||
struct timeval t;
|
struct timespec t;
|
||||||
uint32_t flags;
|
uint32_t flags;
|
||||||
} patty_timer;
|
} patty_timer;
|
||||||
|
|
||||||
|
@ -24,7 +24,11 @@ void patty_timer_start(patty_timer *timer,
|
||||||
|
|
||||||
void patty_timer_stop(patty_timer *timer);
|
void patty_timer_stop(patty_timer *timer);
|
||||||
|
|
||||||
|
void patty_timer_sub(struct timespec *a,
|
||||||
|
struct timespec *b,
|
||||||
|
struct timespec *c);
|
||||||
|
|
||||||
void patty_timer_tick(patty_timer *timer,
|
void patty_timer_tick(patty_timer *timer,
|
||||||
struct timeval *elapsed);
|
struct timespec *elapsed);
|
||||||
|
|
||||||
#endif /* _PATTY_TIMER_H */
|
#endif /* _PATTY_TIMER_H */
|
||||||
|
|
22
src/server.c
22
src/server.c
|
@ -3,6 +3,7 @@
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
|
#include <time.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
|
@ -20,7 +21,7 @@ struct _patty_ax25_server {
|
||||||
int fd, /* fd of UNIX domain socket */
|
int fd, /* fd of UNIX domain socket */
|
||||||
fd_max;
|
fd_max;
|
||||||
|
|
||||||
struct timeval elapsed;
|
struct timespec elapsed;
|
||||||
|
|
||||||
fd_set fds_watch, /* fds to monitor with select() */
|
fd_set fds_watch, /* fds to monitor with select() */
|
||||||
fds_r; /* fds select()ed for reading */
|
fds_r; /* fds select()ed for reading */
|
||||||
|
@ -2018,14 +2019,15 @@ int patty_ax25_server_run(patty_ax25_server *server) {
|
||||||
while (1) {
|
while (1) {
|
||||||
int nready;
|
int nready;
|
||||||
|
|
||||||
struct timeval timeout = { 1, 0 },
|
struct timeval timeout = { 1, 0 };
|
||||||
before,
|
|
||||||
after;
|
struct timespec before,
|
||||||
|
after;
|
||||||
|
|
||||||
memcpy(&server->fds_r, &server->fds_watch, sizeof(server->fds_r));
|
memcpy(&server->fds_r, &server->fds_watch, sizeof(server->fds_r));
|
||||||
|
|
||||||
if (gettimeofday(&before, NULL) < 0) {
|
if (clock_gettime(CLOCK_MONOTONIC, &before) < 0) {
|
||||||
goto error_gettimeofday;
|
goto error_clock_gettime;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((nready = select( server->fd_max,
|
if ((nready = select( server->fd_max,
|
||||||
|
@ -2036,11 +2038,11 @@ int patty_ax25_server_run(patty_ax25_server *server) {
|
||||||
goto error_io;
|
goto error_io;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (gettimeofday(&after, NULL) < 0) {
|
if (clock_gettime(CLOCK_MONOTONIC, &after) < 0) {
|
||||||
goto error_gettimeofday;
|
goto error_clock_gettime;
|
||||||
}
|
}
|
||||||
|
|
||||||
timersub(&after, &before, &server->elapsed);
|
patty_timer_sub(&after, &before, &server->elapsed);
|
||||||
|
|
||||||
if (handle_socks(server) < 0) {
|
if (handle_socks(server) < 0) {
|
||||||
goto error_io;
|
goto error_io;
|
||||||
|
@ -2065,7 +2067,7 @@ int patty_ax25_server_run(patty_ax25_server *server) {
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
error_gettimeofday:
|
error_clock_gettime:
|
||||||
error_io:
|
error_io:
|
||||||
close(server->fd);
|
close(server->fd);
|
||||||
|
|
||||||
|
|
27
src/timer.c
27
src/timer.c
|
@ -5,12 +5,17 @@ int patty_timer_running(patty_timer *timer) {
|
||||||
}
|
}
|
||||||
|
|
||||||
int patty_timer_expired(patty_timer *timer) {
|
int patty_timer_expired(patty_timer *timer) {
|
||||||
return (timer->flags & PATTY_TIMER_RUNNING) && timer->t.tv_sec <= 0? 1: 0;
|
if (!(timer->flags & PATTY_TIMER_RUNNING)) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return timer->t.tv_sec < 0
|
||||||
|
|| (timer->t.tv_sec == 0 && timer->t.tv_nsec <= 0)? 1: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void patty_timer_clear(patty_timer *timer) {
|
void patty_timer_clear(patty_timer *timer) {
|
||||||
timer->t.tv_sec = 0;
|
timer->t.tv_sec = 0;
|
||||||
timer->t.tv_usec = 0;
|
timer->t.tv_nsec = 0;
|
||||||
|
|
||||||
timer->flags &= ~PATTY_TIMER_RUNNING;
|
timer->flags &= ~PATTY_TIMER_RUNNING;
|
||||||
}
|
}
|
||||||
|
@ -18,7 +23,7 @@ void patty_timer_clear(patty_timer *timer) {
|
||||||
void patty_timer_start(patty_timer *timer,
|
void patty_timer_start(patty_timer *timer,
|
||||||
time_t ms) {
|
time_t ms) {
|
||||||
timer->t.tv_sec = ms / 1000;
|
timer->t.tv_sec = ms / 1000;
|
||||||
timer->t.tv_usec = (ms % 1000) * 1000;
|
timer->t.tv_nsec = (ms % 1000) * 1000000;
|
||||||
|
|
||||||
timer->flags |= PATTY_TIMER_RUNNING;
|
timer->flags |= PATTY_TIMER_RUNNING;
|
||||||
}
|
}
|
||||||
|
@ -27,16 +32,24 @@ void patty_timer_stop(patty_timer *timer) {
|
||||||
timer->flags &= ~PATTY_TIMER_RUNNING;
|
timer->flags &= ~PATTY_TIMER_RUNNING;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void patty_timer_sub(struct timespec *a,
|
||||||
|
struct timespec *b,
|
||||||
|
struct timespec *c) {
|
||||||
|
c->tv_nsec = a->tv_nsec - b->tv_nsec;
|
||||||
|
c->tv_sec = a->tv_sec - b->tv_sec - (c->tv_nsec / 1000000000);
|
||||||
|
c->tv_nsec %= 1000000000;
|
||||||
|
}
|
||||||
|
|
||||||
void patty_timer_tick(patty_timer *timer,
|
void patty_timer_tick(patty_timer *timer,
|
||||||
struct timeval *elapsed) {
|
struct timespec *elapsed) {
|
||||||
struct timeval res;
|
struct timespec res;
|
||||||
|
|
||||||
if (!(timer->flags & PATTY_TIMER_RUNNING)) {
|
if (!(timer->flags & PATTY_TIMER_RUNNING)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
timersub(&timer->t, elapsed, &res);
|
patty_timer_sub(&timer->t, elapsed, &res);
|
||||||
|
|
||||||
timer->t.tv_sec = res.tv_sec;
|
timer->t.tv_sec = res.tv_sec;
|
||||||
timer->t.tv_usec = res.tv_usec;
|
timer->t.tv_nsec = res.tv_nsec;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue