Date: Tue, 11 Nov 2008 05:20:05 GMT From: Giorgos Keramidas <keramida@freebsd.org> To: freebsd-bugs@FreeBSD.org Subject: Re: kern/128714: gmtime infinty loop Message-ID: <200811110520.mAB5K5lI073797@freefall.freebsd.org>
index | next in thread | raw e-mail
The following reply was made to PR kern/128714; it has been noted by GNATS.
From: Giorgos Keramidas <keramida@freebsd.org>
To: Bruce Cran <bruce@cran.org.uk>
Cc: bug-followup@freebsd.org
Subject: Re: kern/128714: gmtime infinty loop
Date: Tue, 11 Nov 2008 07:00:06 +0200
On Mon, 10 Nov 2008 07:45:37 -0800, Bruce Cran <bruce@cran.org.uk> wrote:
> On an 8-CURRENT amd64 machine I get the stack trace:
>
> #0 0x00000008007053df in atexit () from /lib/libc.so.7
> #1 0x0000000800706c8e in timeoff () from /lib/libc.so.7
> #2 0x0000000800707355 in gmtime () from /lib/libc.so.7
> #3 0x0000000000400638 in test (t=-33884019326476801) at test.c:7
> #4 0x0000000000400686 in main () at test.c:15
This looks like an exit() handler, running after ^C was pressed or
similar. The real bug seems to be in localtime.ctimesub(). When the
last second of a non-leap year is passed to timesub() it starts
'oscillating' between days = -1 and days = 365:
$ env LD_PRELOAD=$HOME/obj-amd64/$HOME/ws/head/lib/libc/libc.so.7 \
./foo 2>&1 | head -30
days -392176149613 : y 1970 yleap 1 ylen 366
days 260555599 : y -1074453235 yleap 0 ylen 365
days -172760 : y -1073739385 yleap 0 ylen 365
days 365 : y -1073739859 yleap 0 ylen 365
days -1 : y -1073739858 yleap 0 ylen 365
days 365 : y -1073739859 yleap 0 ylen 365
days -1 : y -1073739858 yleap 0 ylen 365
[repeat...]
The following patch fixes this for me on ref8-amd64 at freebsd.org, but
I want to write a mode detailed description of the changes, and test it
a bit more before it is anywhere near 'committable' state. A slightly
less "hacky" version of the patch is probably a good idea too. I don't
like the exception of ``days == year_lengths[yleap]'' near line 1380,
and there's probably a slightly cleaner way to make sure the iteration
converges to the correct date after a finite number of iterations.
The patch is...
%%%
Try to avoid 'oscillating' between -1 and 365 days in timesub().
XXX: A more detailed explanation of why this happens is needed here.
Submitted by: Vladimir Timfeev
PR: kern/128714
Index: lib/libc/stdtime/localtime.c
===================================================================
--- lib/libc/stdtime/localtime.c (revision 184823)
+++ lib/libc/stdtime/localtime.c (working copy)
@@ -1366,7 +1366,7 @@
tmp->tm_wday += DAYSPERWEEK;
y = EPOCH_YEAR;
#define LEAPS_THRU_END_OF(y) ((y) / 4 - (y) / 100 + (y) / 400)
- while (days < 0 || days >= (long) year_lengths[yleap = isleap(y)]) {
+ while (days < 0 || days > (long)year_lengths[yleap = isleap(y)]) {
long newy;
newy = y + days / DAYSPERNYEAR;
@@ -1377,6 +1377,8 @@
LEAPS_THRU_END_OF(y - 1);
y = newy;
}
+ if (days == (long)year_lengths[yleap])
+ days--;
tmp->tm_year = y - TM_YEAR_BASE;
tmp->tm_yday = (int) days;
ip = mon_lengths[yleap];
%%%
home |
help
Want to link to this message? Use this
URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200811110520.mAB5K5lI073797>
