[tz] timegm() function and state

Doug Bailey DBailey at qnx.com
Thu Aug 2 21:52:47 UTC 2012


One of my users reported that the first time timegm() is called, it returns -1.  Investigating, it seems that there's a problem with the gmtptr state.

Take the following code:
    int main(int argc, char *argv[]) {
        struct tm localt;

        localt.tm_sec = 0;
        localt.tm_min = 0;
        localt.tm_hour = 0;
        localt.tm_mday = 1;
        localt.tm_year = 113;
        localt.tm_mon = 0;
        localt.tm_wday = 0;
        localt.tm_yday = 0;
        localt.tm_isdst = 0;
        localt.tm_gmtoff = 0;
        localt.tm_zone = 0;
        mktime(&localt);

        printf("asctime: %s", asctime(&localt));
        printf("timegm(&localt) = %d (errno %s)\n", timegm(&localt), strerror(errno));
        printf("timegm(&localt) = %d (errno %s)\n", timegm(&localt), strerror(errno));
        printf("timegm(&localt) = %d (errno %s)\n", timegm(&localt), strerror(errno));

        return 0;
    }

Run it and you get:
    asctime: Tue Jan  1 00:00:00 2013
    timegm(&localt) = -1 (errno No such process)
    timegm(&localt) = 1356998400 (errno No such process)
    timegm(&localt) = 1356998400 (errno No such process)

The first time timegm() is invoked, it fails.  Subsequent invocations work correctly.

I didn't manage to track down the root problem, but I found if I forced gmtptr to load (as gmtsub should), then everything works correctly.

time_t
timegm(tmp)
struct tm * const	tmp;
{
	if (!gmt_is_set) {
		gmt_is_set = TRUE;
#ifdef ALL_STATE
		gmtptr = (struct state *) calloc(1, sizeof *gmtptr);
		if (gmtptr != NULL)
#endif /* defined ALL_STATE */
			gmtload(gmtptr);
	}
	if (tmp != NULL)
		tmp->tm_isdst = 0;
	return time1(tmp, gmtsub, 0L);
}


I just copied the gmt_is_set test from gmtsub.  I realize that gmtsub gets called anyways (timegm->time1->time2->gmtsub), but maybe the context doesn't get loaded quickly enough.

I haven't tested, but I suspect that timeoff will have the same problem since it also invokes time1(..,gmtsub,..) without first ensuring the gmt context is loaded.

Doug




More information about the tz mailing list