[tz] NetBSD vs Darwin timezone API (was: tzdata2016g missing version info)

Guy Harris guy at alum.mit.edu
Fri Nov 11 01:12:17 UTC 2016

On Nov 10, 2016, at 2:44 PM, Paul Eggert <eggert at cs.ucla.edu> wrote:

> On 11/10/2016 02:04 PM, Guy Harris wrote:
>>> I don't see an easy way around this problem with the current Darwin API.
>> With the current*UNIX*  API.
> The NetBSD API gives applications a way to get an immutable time zone object, so that multiple operations like localtime_rz and mktime_z can use consistent rules. This was originally designed for multithreading (so that different threads can be in different time zones) but it also has the property that time zone rules don't change once determined (which helps performance). Emacs uses this API if available, so Emacs should be reasonably immune to these races on NetBSD.
> NetBSD doesn't look for changes to the installed tz binary files, as Darwin does.

As I remember from the discussions I mentioned, Darwin doesn't do so, either.  What it *does* have are notifications (sent, I think, using the "notification" mechanism - "man 3 notify" on macOS) sent out when the *current time zone* changes (either manually from System Preferences or automatically from a location change).

> If the NetBSD API were implemented atop Darwin, perhaps the Darwin tzalloc operation should have a flag specifying whether the caller wants the time zone object to be immutable or potentially updated after every call.

There are two issues here:

	1) is a timezone object immutable across changes to *the time zone data files*?

	2) is a timezone object obtained from tzalloc(NULL) immutable across changes to *which tzdb zone is the current zone*?

The only place where the current Darwin behavior is an issue is, as far as I know, 2), as I don't think changes to the time zone files provoke a reload of the file.

The tzalloc() man page says

	A NULL pointer may be passed to tzalloc() instead of a timezone name, to
	refer to the current system timezone.

The question is whether "current timezone" means "current as of the time it's called" or "special time zone object that changes when the current time zone changes".

I'm guessing that it means the former on NetBSD.

For systems that support the time zone changing out from under applications, I can see two ways to handle current time zone changes for tzalloc() (there may be more ways):

	1) the timezone object returned by tzalloc(NULL) is mutable if the current time zone changes, and the object returned by tzalloc_flags(NULL, TZA_MUTABLE) is mutable if the tzdata changes or the current time zone changes;

	2) the timezone object returned by tzalloc(NULL) is immutable, the object returned by tzalloc_flags(NULL, TZA_MUTABLE) is mutable only if the tzdata changes, *and* we have an API that delivers "the current time zone changed" events (the reference implementation would never deliver an event, but implementations based on the reference implementation, and independent implementations, could).

A third possibility is to have the objects *always* be immutable, and deliver both "current time zone changed" and "tzdata was updated" events.

The behavior of localtime() for a current time zone change probably should *not* be specified - the only specification that won't result in Apple ignoring the specification is "localtime() always tracks the current time zone, even if it changes", and there are probably other systems that would reject *requiring* it to track the current time zone (as they'd have to implement something to detect those changes in arbitrary programs using localtime() etc., even something as simple as

	#include <stdio.h>
	#include <time.h>
	#include <unistd.h>

		time_t now;

		for (;;) {
			now = time(NULL);
			printf("%s", ctime(&now));
		return 0;

which *does*, in fact, track time zone changes on macOS - I just tested it on my macOS Sierra machine with manual zone changes).

>> I don't know what Emacs is trying to compute, but perhaps there needs to be an API that atomically gives it what it's trying to compute
> Emacs is inferring the daylight-saving rules by making multiple calls to localtime. Essentially, Emacs wants a consistent and complete snapshot of the current rule set for all times from now into the indefinite future.

To what use does it put that snapshot?  (And is it assuming it's running on an immobile machine?)

More information about the tz mailing list