bug-gnulib@gnu.org mirror (unofficial)
 help / color / mirror / Atom feed
From: Bruno Haible <bruno@clisp.org>
To: bug-gnulib@gnu.org
Subject: Re: MT-unsafe time modules
Date: Sat, 10 Feb 2024 12:10:44 +0100	[thread overview]
Message-ID: <2364117.OYXXYNVTWy@nimes> (raw)
In-Reply-To: <3755090.VQhiAETyHQ@nimes>

> * These need to be made MT-safe:
> mktime, mktime-internal
> timegm
> time_r
> time_rz
> c-nstrftime, nstrftime
> parse-datetime, parse-datetime2

For these modules, the next function to provide in an MT-safe way is
localtime_r. On native Windows, when the 'localtime_s' function [1][2]
is not available, such as on the older Windows versions that Emacs cares
about, the solution is to use GetTimeZoneInformation [3].

The next function, then, is a localtime_r variant with time zone argument.
It's needed
  * for implementing 'localtime_rz', in the 'time_rz' module.
  * as a 'convert' subroutine for the 'mktime_z' function, in the 'time_rz'
  * indirectly by nstrftime, c-nstrftime, fprintftime, parse-datetime,
    that all rely on 'time_rz'.

Such a localtime_r variant with time zone argument needs to use the
time zone database that the system has access to. But the only public
API that the system offers (localtime{,_r}) relies on the environment "TZ"
variable "TZ" and some global variables (tzname, timezone, daylight)
derived from it, and changing an environment variable is not MT-safe.

So, there are only two approaches that I can see:

  (a) Read the time zone database information into memory from a file
      shipped together with Gnulib. This is how the libstdc++ implementation
      of the C++ time zone functionality [4] does it [5][6].

  (b) Read the time zone database information into memory from the
      system locations, in a platform dependent way.

The code for doing this exists in glibc and libstdc++ and would need to be

BUT this is a major project: it would take several weeks.

And it is overkill for
  - the proposed safer_ctime function,
  - most practical uses of nstrftime, c_nstrftime.
Namely, for these cases, a general timezone_t is not needed, only a boolean
that covers the case of local time and GMT/UTC. And these cases *can* be
done in a multithread-safe way:
  - The value of "TZ" does not need to be changed on the fly.
  - The values of the global variables (tzname, timezone, daylight) may
    be set through tzset(), in a thread, but these values are OK for the
    other threads as well, since getenv ("TZ") is the same in all threads.
  - The GMT/UTC case can be implemented by not looking at "TZ" nor the
    global variables.

I therefore intend to do this latter part:
  1) Make localtime_r on native Windows MT-safe.
  2) Document which LGPLed interfaces are not MT-safe.
  3) Provide an MT-safe and bug-fixed 'strftime' function (that assumes
     local time, no time zone argument).
  4) Provide an analogous 'c_strftime' function that does not even access
  5) The proposed safer_ctime, based on localtime_r and c_strftime.


[1] https://learn.microsoft.com/en-us/cpp/c-runtime-library/reference/localtime-s-localtime32-s-localtime64-s
[2] https://learn.microsoft.com/en-us/previous-versions/a442x3ye
[3] https://learn.microsoft.com/en-us/windows/win32/api/timezoneapi/nf-timezoneapi-gettimezoneinformation
[4] https://en.cppreference.com/w/cpp/chrono
[5] https://gcc.gnu.org/git/?p=gcc.git;a=blob;f=libstdc%2B%2B-v3/include/std/chrono
[6] https://gcc.gnu.org/git/?p=gcc.git;a=tree;f=libstdc%2B%2B-v3/src/c%2B%2B20

  parent reply	other threads:[~2024-02-10 11:11 UTC|newest]

Thread overview: 10+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-02-09 17:43 MT-unsafe time modules Bruno Haible
2024-02-09 20:22 ` Bruno Haible
2024-02-10 11:10 ` Bruno Haible [this message]
2024-02-11 12:46   ` localtime on native Windows Bruno Haible
2024-02-13  2:02     ` Paul Eggert
2024-02-18  2:38       ` Bruno Haible
2024-02-18  4:50         ` Paul Eggert
2024-02-18 14:38           ` Bruno Haible
2024-02-18 19:05             ` Paul Eggert
2024-02-11 10:43 ` MT-unsafe time modules Bruno Haible

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:

  List information: https://lists.gnu.org/mailman/listinfo/bug-gnulib

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=2364117.OYXXYNVTWy@nimes \
    --to=bruno@clisp.org \
    --cc=bug-gnulib@gnu.org \


* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).