Skip to content

Commit

Permalink
ping: fix dead loop problem
Browse files Browse the repository at this point in the history
This change will make ping exit normally when system clock is changed during
time time when ping runs, and more imporatntly the is set before start time.
Earlier that caused infinite loop.

Fixes: #276
  • Loading branch information
lac-0073 authored and kerolasa committed Aug 29, 2020
1 parent 469b41a commit 4fd276c
Show file tree
Hide file tree
Showing 2 changed files with 24 additions and 10 deletions.
16 changes: 15 additions & 1 deletion ping/ping.h
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,7 @@ struct ping_rts {
int preload;
int deadline; /* time to die */
int lingertime;
struct timeval start_time, cur_time;
struct timespec start_time, cur_time;
volatile int exiting;
volatile int status_snapshot;
int confirm;
Expand Down Expand Up @@ -294,6 +294,20 @@ static inline void tvsub(struct timeval *out, struct timeval *in)
out->tv_sec -= in->tv_sec;
}

/*
* tssub --
* Subtract 2 timespec structs: out = out - in. Out is assumed to
* be >= in.
*/
static inline void tssub(struct timespec *out, struct timespec *in)
{
if ((out->tv_nsec -= in->tv_nsec) < 0) {
--out->tv_sec;
out->tv_nsec += 1000000000;
}
out->tv_sec -= in->tv_sec;
}

static inline void set_signal(int signo, void (*handler)(int))
{
struct sigaction sa;
Expand Down
18 changes: 9 additions & 9 deletions ping/ping_common.c
Original file line number Diff line number Diff line change
Expand Up @@ -313,15 +313,15 @@ int pinger(struct ping_rts *rts, ping_func_set_st *fset, socket_st *sock)

/* Check that packets < rate*time + preload */
if (rts->cur_time.tv_sec == 0) {
gettimeofday(&rts->cur_time, NULL);
clock_gettime(CLOCK_MONOTONIC_RAW, &rts->cur_time);
tokens = rts->interval * (rts->preload - 1);
} else {
long ntokens, tmp;
struct timeval tv;
struct timespec tv;

gettimeofday(&tv, NULL);
clock_gettime(CLOCK_MONOTONIC_RAW, &tv);
ntokens = (tv.tv_sec - rts->cur_time.tv_sec) * 1000 +
(tv.tv_usec - rts->cur_time.tv_usec) / 1000;
(tv.tv_nsec - rts->cur_time.tv_nsec) / 1000000;
if (!rts->interval) {
/* Case of unlimited flood is special;
* if we see no reply, they are limited to 100pps */
Expand Down Expand Up @@ -531,7 +531,7 @@ void setup(struct ping_rts *rts, socket_st *sock)
sigemptyset(&sset);
sigprocmask(SIG_SETMASK, &sset, NULL);

gettimeofday(&rts->start_time, NULL);
clock_gettime(CLOCK_MONOTONIC_RAW, &rts->start_time);

if (rts->deadline) {
struct itimerval it;
Expand Down Expand Up @@ -868,10 +868,10 @@ static long llsqrt(long long a)
*/
int finish(struct ping_rts *rts)
{
struct timeval tv = rts->cur_time;
struct timespec tv = rts->cur_time;
char *comma = "";

tvsub(&tv, &rts->start_time);
tssub(&tv, &rts->start_time);

putchar('\n');
fflush(stdout);
Expand All @@ -891,7 +891,7 @@ int finish(struct ping_rts *rts)
#endif
printf(_(", %g%% packet loss"),
(float)((((long long)(rts->ntransmitted - rts->nreceived)) * 100.0) / rts->ntransmitted));
printf(_(", time %ldms"), 1000 * tv.tv_sec + (tv.tv_usec + 500) / 1000);
printf(_(", time %ldms"), 1000 * tv.tv_sec + (tv.tv_nsec + 500000) / 1000000);
}

putchar('\n');
Expand Down Expand Up @@ -924,7 +924,7 @@ int finish(struct ping_rts *rts)
}

if (rts->nreceived && (!rts->interval || rts->opt_flood || rts->opt_adaptive) && rts->ntransmitted > 1) {
int ipg = (1000000 * (long long)tv.tv_sec + tv.tv_usec) / (rts->ntransmitted - 1);
int ipg = (1000000 * (long long)tv.tv_sec + tv.tv_nsec / 1000) / (rts->ntransmitted - 1);

printf(_("%sipg/ewma %d.%03d/%d.%03d ms"),
comma, ipg / 1000, ipg % 1000, rts->rtt / 8000, (rts->rtt / 8) % 1000);
Expand Down

0 comments on commit 4fd276c

Please sign in to comment.