[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