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> 2003-09-10 Hrvoje Niksic <hniksic@xemacs.org>
* host.c (lookup_host): Print the result of the DNS lookup. * 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
#endif /* not WINDOWS */ #endif /* not WINDOWS */
struct wget_timer {
#ifdef TIMER_GETTIMEOFDAY #ifdef TIMER_GETTIMEOFDAY
long secs; typedef struct timeval wget_sys_time;
long usecs;
#endif #endif
#ifdef TIMER_TIME #ifdef TIMER_TIME
time_t secs; typedef time_t wget_sys_time;
#endif #endif
#ifdef TIMER_WINDOWS #ifdef TIMER_WINDOWS
ULARGE_INTEGER wintime; typedef ULARGE_INTEGER wget_sys_time;
#endif #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 /* 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); xfree (wt);
} }
/* Reset timer WT. This establishes the starting point from which /* Store system time to WST. */
wtimer_elapsed() will return the number of elapsed
milliseconds. It is allowed to reset a previously used timer. */
void static void
wtimer_reset (struct wget_timer *wt) wtimer_sys_set (wget_sys_time *wst)
{ {
#ifdef TIMER_GETTIMEOFDAY #ifdef TIMER_GETTIMEOFDAY
struct timeval t; gettimeofday (wst, NULL);
gettimeofday (&t, NULL);
wt->secs = t.tv_sec;
wt->usecs = t.tv_usec;
#endif #endif
#ifdef TIMER_TIME #ifdef TIMER_TIME
wt->secs = time (NULL); time (wst);
#endif #endif
#ifdef TIMER_WINDOWS #ifdef TIMER_WINDOWS
@ -1600,8 +1606,38 @@ wtimer_reset (struct wget_timer *wt)
SYSTEMTIME st; SYSTEMTIME st;
GetSystemTime (&st); GetSystemTime (&st);
SystemTimeToFileTime (&st, &ft); SystemTimeToFileTime (&st, &ft);
wt->wintime.HighPart = ft.dwHighDateTime; wst->HighPart = ft.dwHighDateTime;
wt->wintime.LowPart = ft.dwLowDateTime; 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 #endif
} }
@ -1612,27 +1648,34 @@ wtimer_reset (struct wget_timer *wt)
long long
wtimer_elapsed (struct wget_timer *wt) wtimer_elapsed (struct wget_timer *wt)
{ {
#ifdef TIMER_GETTIMEOFDAY wget_sys_time now;
struct timeval t; long elapsed;
gettimeofday (&t, NULL);
return (t.tv_sec - wt->secs) * 1000 + (t.tv_usec - wt->usecs) / 1000;
#endif
#ifdef TIMER_TIME wtimer_sys_set (&now);
time_t now = time (NULL); elapsed = wt->elapsed_pre_start + wtimer_sys_diff (&now, &wt->start);
return 1000 * (now - wt->secs);
#endif
#ifdef WINDOWS /* Ideally we'd just return the difference between NOW and
FILETIME ft; wt->start. However, the system timer can be set back, and we
SYSTEMTIME st; could return a value smaller than when we were last called, even
ULARGE_INTEGER uli; a negative value. Both of these would confuse the callers, which
GetSystemTime (&st); expect us to return monotonically nondecreasing values.
SystemTimeToFileTime (&st, &ft);
uli.HighPart = ft.dwHighDateTime; Therefore: if ELAPSED is smaller than its previous known value,
uli.LowPart = ft.dwLowDateTime; we reset wt->start to the current time and effectively start
return (long)((uli.QuadPart - wt->wintime.QuadPart) / 10000); measuring from this point. But since we don't want the elapsed
#endif 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 /* Return the assessed granularity of the timer implementation. This