1
0
mirror of https://github.com/moparisthebest/wget synced 2024-07-03 16:38:41 -04:00

[svn] Fixed a long-standing bug in the timer code that would cause Wget to

crash when the system time was set back during a Wget run.
Message-ID: <m3znh8wag9.fsf@hniksic.iskon.hr>
This commit is contained in:
hniksic 2003-09-13 16:12:45 -07:00
parent 7e7ce3dc0e
commit ebea9e7e0b
2 changed files with 93 additions and 36 deletions

View File

@ -1,3 +1,17 @@
2003-09-14 Hrvoje Niksic <hniksic@xemacs.org>
* utils.c (wtimer_sys_set): Extracted the code that sets the
current time here.
(wtimer_reset): Call it.
(wtimer_sys_diff): Extracted the code that calculates the
difference between two system times here.
(wtimer_elapsed): Call it.
(wtimer_elapsed): Don't return a value smaller than the previous
one, which could previously happen when system time is set back.
Instead, reset start time to current time and note the elapsed
offset for future calculations. The returned times are now
guaranteed to be monotonically nondecreasing.
2003-09-10 Hrvoje Niksic <hniksic@xemacs.org>
* host.c (lookup_host): Print the result of the DNS lookup.

View File

@ -1532,19 +1532,30 @@ number_to_string (char *buffer, long number)
# endif
#endif /* not WINDOWS */
struct wget_timer {
#ifdef TIMER_GETTIMEOFDAY
long secs;
long usecs;
typedef struct timeval wget_sys_time;
#endif
#ifdef TIMER_TIME
time_t secs;
typedef time_t wget_sys_time;
#endif
#ifdef TIMER_WINDOWS
ULARGE_INTEGER wintime;
typedef ULARGE_INTEGER wget_sys_time;
#endif
struct wget_timer {
/* The starting point in time which, subtracted from the current
time, yields elapsed time. */
wget_sys_time start;
/* The most recent elapsed time, calculated by wtimer_elapsed().
Measured in milliseconds. */
long elapsed_last;
/* Approximately, the time elapsed between the true start of the
measurement and the time represented by START. */
long elapsed_pre_start;
};
/* Allocate a timer. It is not legal to do anything with a freshly
@ -1577,22 +1588,17 @@ wtimer_delete (struct wget_timer *wt)
xfree (wt);
}
/* Reset timer WT. This establishes the starting point from which
wtimer_elapsed() will return the number of elapsed
milliseconds. It is allowed to reset a previously used timer. */
/* Store system time to WST. */
void
wtimer_reset (struct wget_timer *wt)
static void
wtimer_sys_set (wget_sys_time *wst)
{
#ifdef TIMER_GETTIMEOFDAY
struct timeval t;
gettimeofday (&t, NULL);
wt->secs = t.tv_sec;
wt->usecs = t.tv_usec;
gettimeofday (wst, NULL);
#endif
#ifdef TIMER_TIME
wt->secs = time (NULL);
time (wst);
#endif
#ifdef TIMER_WINDOWS
@ -1600,8 +1606,38 @@ wtimer_reset (struct wget_timer *wt)
SYSTEMTIME st;
GetSystemTime (&st);
SystemTimeToFileTime (&st, &ft);
wt->wintime.HighPart = ft.dwHighDateTime;
wt->wintime.LowPart = ft.dwLowDateTime;
wst->HighPart = ft.dwHighDateTime;
wst->LowPart = ft.dwLowDateTime;
#endif
}
/* Reset timer WT. This establishes the starting point from which
wtimer_elapsed() will return the number of elapsed
milliseconds. It is allowed to reset a previously used timer. */
void
wtimer_reset (struct wget_timer *wt)
{
/* Set the start time to the current time. */
wtimer_sys_set (&wt->start);
wt->elapsed_last = 0;
wt->elapsed_pre_start = 0;
}
static long
wtimer_sys_diff (wget_sys_time *wst1, wget_sys_time *wst2)
{
#ifdef TIMER_GETTIMEOFDAY
return ((wst1->tv_sec - wst2->tv_sec) * 1000
+ (wst1->tv_usec - wst2->tv_usec) / 1000);
#endif
#ifdef TIMER_TIME
return 1000 * (*wst1 - *wst2);
#endif
#ifdef WINDOWS
return (long)(wst1->QuadPart - wst2->QuadPart) / 10000;
#endif
}
@ -1612,27 +1648,34 @@ wtimer_reset (struct wget_timer *wt)
long
wtimer_elapsed (struct wget_timer *wt)
{
#ifdef TIMER_GETTIMEOFDAY
struct timeval t;
gettimeofday (&t, NULL);
return (t.tv_sec - wt->secs) * 1000 + (t.tv_usec - wt->usecs) / 1000;
#endif
wget_sys_time now;
long elapsed;
#ifdef TIMER_TIME
time_t now = time (NULL);
return 1000 * (now - wt->secs);
#endif
wtimer_sys_set (&now);
elapsed = wt->elapsed_pre_start + wtimer_sys_diff (&now, &wt->start);
#ifdef WINDOWS
FILETIME ft;
SYSTEMTIME st;
ULARGE_INTEGER uli;
GetSystemTime (&st);
SystemTimeToFileTime (&st, &ft);
uli.HighPart = ft.dwHighDateTime;
uli.LowPart = ft.dwLowDateTime;
return (long)((uli.QuadPart - wt->wintime.QuadPart) / 10000);
#endif
/* Ideally we'd just return the difference between NOW and
wt->start. However, the system timer can be set back, and we
could return a value smaller than when we were last called, even
a negative value. Both of these would confuse the callers, which
expect us to return monotonically nondecreasing values.
Therefore: if ELAPSED is smaller than its previous known value,
we reset wt->start to the current time and effectively start
measuring from this point. But since we don't want the elapsed
value to start from zero, we set elapsed_pre_start to the last
elapsed time and increment all future calculations by that
amount. */
if (elapsed < wt->elapsed_last)
{
wt->start = now;
wt->elapsed_pre_start = wt->elapsed_last;
elapsed = wt->elapsed_last;
}
wt->elapsed_last = elapsed;
return elapsed;
}
/* Return the assessed granularity of the timer implementation. This