[tz] Thread-safe localtime(3) (was Re: Reading binary files)

Guy Harris guy at alum.mit.edu
Wed Nov 2 19:08:48 UTC 2011

On Nov 2, 2011, at 10:12 AM, Bennett Todd wrote:

> It'd surely be nice if this reorg could be propagated to tzcode, in C, ultimately to wend its way into libc everywhere; forking or independently reimplementing tzcode carries a maintenance cost, as the tzdata format isn't quite completely set in stone yet, and as sufficiently clever legislators cook up sufficiently brilliant schemes to "save daylight", it's possible tzdata format and tzcode may have to co-evolve again.
> Any folks on this list have opinions about how the tzset/localtime api should best evolve?

I think that, all other things being equal, if it's already evolved on at least one UN*X, it should evolve in the same direction, as tzcode is used as the basis of many libc implementations (*BSD, Mac OS X, maybe Solaris if they're keeping up with changes).

I.e., I'd go with Christos Zoulas' APIs unless either

	1) some other UN*X has a different API, at which point the multiple APIs should be investigated


	2) there's a significant problem with them.

>From a quick look at the NetBSD APIs, we have:

timezone_t tzalloc(const char *name);
	takes a time zone name as an argument, and returns NULL on failure to load that zone and a timezone_t (an opaque handle, implemented as a pointer to an opaque structure) on success

void tzfree(const timezone_t sp);
	releases the result of tzalloc()

struct tm *localtime_rz(const timezone_t sp, const time_t * __restrict timep, struct tm *tmp);
	given a timezone_t and a time_t, fills in a struct tm - presumably returns the struct tm * passed to it

time_t mktime_z(const timezone_t sp, struct tm *tmp);
	given a timezone_t and a struct tm, returns a time_t

size_t strftime_z(const timezone_t sp, char * const s, const size_t maxsize, const char * const format, const struct tm * const t);
	given a timezone_t, a struct tm, and a format, fills in a string with the time formatted according to the string

Presumably the timezone_t is needed for the time zone name, as

	1) even if NetBSD might have tm_gmtoff and tm_zone fields in struct tm, not all systems will necessarily have it


	2) even if it does, the problem of "what happens if tm_zone points to something in the timezone state and that gets freed before a reference is made to the struct tm?" remains.

I think having APIs that explicitly take a loaded time zone as an argument is something we should do, as thread safety isn't the only issue; there are reasons to have more than one time zone used for time conversions within a given single thread of control.

More information about the tz mailing list