[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Re: Weird time-zone oscillation



On 12/13/2009 11:10 PM, Kumar Appaiah wrote:
On Sun, Dec 13, 2009 at 10:57:24PM +0100, David Kubicek wrote:
This is the first time I've seen this, though, and I use strptime()
often in my SW, mostly for timestamps which would be discovered by
people rather quickly! :) Are you sure you're not using an alternative
impl. of libc?

Well, in Debian, we use eglibc:

http://packages.qa.debian.org/e/eglibc.html
http://www.eglibc.org/home

Yeah, I've heard about it, that's why I get my libc from Ubuntu since. :) These are exactly the issues that were talked about.

You see this is not strptime() issue, right? To be portable, we *ought to* set tm_isdst = -1 after, but here the issue comes from mktime screwing up. It's about the *sequence* strptime() -> mktime().

Anyway, I've run this binary on 15 servers now and all worked fine
(RHEL4/5, SuSE, Debian). Each and every libc version I've tested it on
sets tm_isdst to -1. That means "DST not yet detected", if mktime() is
called later, it will know it has to detect DST itself. If your libc
*doesn't* do this for you, setting it to *0* pre-call is even worse. It
means "no DST" and mktime will not verify it. Only -1 is acceptable as
input to mktime, unless of course you check DST yourself and set 0/1 as
an informed action.

Well, let me add to your statement that we've been able to reproduce
this error ONLY on amd64 machines. I am also surprised at why this is
the case, and I'll dig into your advice above subsequently. However,
note this, from my mktime man page:

        The mktime() function modifies the fields of the tm structure
        as follows: tm_wday and tm_yday are set to values determined
        from the contents of the other fields; if structure members are
        outside their valid interval, they will be normalized (so that,
        for example, 40 October is changed into 9 November); tm_isdst
        is set (regardless of its initial value) to a positive value or
        to 0, respectively, to indicate whether DST is or is not in
        effect at the specified time.  Calling mktime() also sets the
        exter‐ nal variable tzname with information about the current
        timezone.

See, this is crap. :) It means the bug is in libc (eglibc). It says it disregards tm_isdst - whatever the value - but as you've tested yourself, it didn't disregard it. Depending on the stack junk bytes left in tm_isdst, it added DST one time, dind't the other.

Not only is eglibc broken with regards to its own documentation, it goes against the standard too.

Quoting Single Unix Specification v3:

"A positive or 0 value for tm_isdst shall cause mktime() to presume initially that Daylight Savings Time, respectively, is or is not in effect for the specified time. A _negative_value_ for tm_isdst shall cause mktime() to _attempt_to_determine_ whether Daylight Savings Time is in effect for the specified time."

Eglibc says it attempts to determine DST in any case, but it doesn't. It returns random junk.

This is what GNU libc has to say:

"The value specified in the tm_isdst field *informs* mktime() whether or not daylight saving time (DST) is in effect for the time supplied in the tm structure: a positive value means DST is in effect; zero means that DST is not in effect; and a negative value means that mktime() should (use timezone information and system databases to) attempt to determine whether DST is in effect at the specified time."

See, that's correct according to SUSv3. GNU libc also sets tm_isdst to -1 on return from strptime(), which works nicely with subsequent calls to properly implemented mktime().

I do believe eglibc should fix their documentation or their code. I hate how Debian turned us into guinea pigs with this crap!


--
David Kubicek


Reply to: