Austin Group Defect Tracker

Aardvark Mark IV


Viewing Issue Simple Details Jump to Notes ] Issue History ] Print ]
ID Category Severity Type Date Submitted Last Update
0001794 [1003.1(2016/18)/Issue7+TC2] System Interfaces Editorial Enhancement Request 2024-01-06 23:11 2024-01-06 23:11
Reporter steffen View Status public  
Assigned To
Priority normal Resolution Open  
Status New  
Name steffen
Organization
User Reference
Section localtime, gmtime
Page Number in transit
Line Number (Line or range of lines)
Interp Status ---
Final Accepted Text
Summary 0001794: Please add tzalloc/tzfree and localtime_rz, mktime_z interfaces
Description [I copy a mail from austin-group-l@]

As stated in [1] the localtime() and mktime() series of functions
have the inherent problem of not being thread-safe regarding
possible changes to the time zone: in a pure POSIX environment
changes to TZ always affect global data.

If my memory serves correctly, about a decade ago the NetBSD
project contacted the IANA TZ maintainer in order to upstream
a new, truly thread-safe interface that addresses this issue.
Since some time in 2014 (see [1]) the IANA TZ database, which
includes the Public Domain aka open source code as is used by many
projects to implement the time related programming interface,
includes a new series of functions:

       timezone_t tzalloc(char const *TZ);
       void tzfree(timezone_t tz);

       struct tm *localtime_rz(timezone_t restrict zone,
           time_t const *restrict clock,
           struct tm *restrict result);
           struct tm *restrict tm);
       time_t mktime_z(timezone_t restrict zone,
           struct tm *restrict tm);

  [1] https://austingroupbugs.net/view.php?id=1788 [^]

If POSIX would offer this interface, the open source (public
domain) code and manual of which are available via the IANA TZ,
truly "thread-safe" time programming becomes possible in POSIX.

This is especially important if no CLOCK_TAI is available.
For an example, here is what the widely used NTP server chrony
performs in order to achieve its task:

  tm = gmtime(&when);
  if (!tm)
    return tz_leap;

  stm = *tm;

  /* Temporarily switch to the timezone containing leap seconds */
  tz_env = getenv("TZ");
  if (tz_env) {
    if (strlen(tz_env) >= sizeof (tz_orig))
      return tz_leap;
    strcpy(tz_orig, tz_env);
  }
  setenv("TZ", leap_tzname, 1);
  tzset();

  /* Get the TAI-UTC offset, which started at the epoch at 10 seconds */
  t = mktime(&stm);
  if (t != -1)
    tz_tai_offset = t - when + 10;

  /* Set the time to 23:59:60 and see how it overflows in mktime() */
  stm.tm_sec = 60;
  stm.tm_min = 59;
  stm.tm_hour = 23;

  t = mktime(&stm);

  if (tz_env)
    setenv("TZ", tz_orig, 1);
  else
    unsetenv("TZ");
  tzset();

  if (t == -1)
    return tz_leap;

  if (stm.tm_sec == 60)
    tz_leap = LEAP_InsertSecond;
  else if (stm.tm_sec == 1)
    tz_leap = LEAP_DeleteSecond;

  *tai_offset = tz_tai_offset;

This is especially important if no CLOCK_TAI is available.
For an example, here is what the widely used NTP server chrony
performs in order to achieve its task:

  tm = gmtime(&when);
  if (!tm)
    return tz_leap;

  stm = *tm;

  /* Temporarily switch to the timezone containing leap seconds */
  tz_env = getenv("TZ");
  if (tz_env) {
    if (strlen(tz_env) >= sizeof (tz_orig))
      return tz_leap;
    strcpy(tz_orig, tz_env);
  }
  setenv("TZ", leap_tzname, 1);
  tzset();

  /* Get the TAI-UTC offset, which started at the epoch at 10 seconds */
  t = mktime(&stm);
  if (t != -1)
    tz_tai_offset = t - when + 10;

  /* Set the time to 23:59:60 and see how it overflows in mktime() */
  stm.tm_sec = 60;
  stm.tm_min = 59;
  stm.tm_hour = 23;

  t = mktime(&stm);

  if (tz_env)
    setenv("TZ", tz_orig, 1);
  else
    unsetenv("TZ");
  tzset();

  if (t == -1)
    return tz_leap;

  if (stm.tm_sec == 60)
    tz_leap = LEAP_InsertSecond;
  else if (stm.tm_sec == 1)
    tz_leap = LEAP_DeleteSecond;

  *tai_offset = tz_tai_offset;

I want to point out that setting an environment variable can be
a costly operation, but moreover changing the timezone as such
may involve several file system operations, being a potentially
very expensive operation. (By the way the draft 4 uses "file
system" as well as "filesystem".)

With the new interface two timezone objects can be preallocated,
and the operations are totally detached from global data and
multithread-safe.
Desired Action Please sponsor and add the tzalloc/tzfree and localtime_rz, mktime_z interfaces.

They are already available on NetBSD, and soon will be released on Android.
The Public Domain code of the IANA TZ includes these functions and their manual pages; its' maintainer is also a major contributor to the most widely used Linux C library (ie a code sync is to be expected fast as necessary).
Tags No tags attached.
Attached Files

- Relationships

There are no notes attached to this issue.

- Issue History
Date Modified Username Field Change
2024-01-06 23:11 steffen New Issue
2024-01-06 23:11 steffen Name => steffen
2024-01-06 23:11 steffen Section => localtime, gmtime
2024-01-06 23:11 steffen Page Number => in transit
2024-01-06 23:11 steffen Line Number => (Line or range of lines)


Mantis 1.1.6[^]
Copyright © 2000 - 2008 Mantis Group
Powered by Mantis Bugtracker