mailing list of musl libc
 help / color / mirror / code / Atom feed
* [musl] Time zone has not updated after call tzset()
@ 2023-02-11  6:53 zhoujingqiang (A)
  2023-02-11 14:10 ` alice
  0 siblings, 1 reply; 5+ messages in thread
From: zhoujingqiang (A) @ 2023-02-11  6:53 UTC (permalink / raw)
  To: musl
  Cc: yubing (C), liudongxu, wangyunhe (A), qiuguorui, Wanglieming (VRP SSP)

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain; charset="gb2312", Size: 3677 bytes --]

Hello,

Normally, /etc/localtime is a soft link to a file that stores time zone information.

Without setting the TZ environment variable, I change the time zone by changing the file linked to /etc/localtime. After calling tzset(), I find that the time zone does not change. The test code is as follows:

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

void sig(int signum)
{
        time_t now = (time_t)-1;
        struct tm result;

        now = time(NULL);
        tzset();
        localtime_r(&now, &result);

#define PSSP_DATETIME_LOCAL_FORMAT "%Y-%m-%dT%H:%M:%S%z"
        char line[1024];
        strftime(line, sizeof(line), PSSP_DATETIME_LOCAL_FORMAT, &result);
        printf("result: %s\n", line);
}

int main(void)
{

        signal(41, sig);
        while (1) {
                sig(41);
                sleep(20);
        }
        return 0;
}

The result is as follows£º

result: 2023-02-11T10:07:01+0800
result: 2023-02-11T10:07:21+0800
result: 2023-02-11T10:07:41+0800
result: 2023-02-11T10:08:01+0800

The test steps is as follows:


1.       The test program get localtime every 20 seconds.

2.       Initially, /etc/localtime links to /usr/share/zoneinfo/Asia/Hong_Kong
date ¨CR: Sat, 11 Feb 2023 10:40:00 +0800

3.       After the test program has been running for a while, change /etc/localtime to link to /usr/share/zoneinfo/Asia/Aden
date ¨CR: Sat, 11 Feb 2023 05:07:30 +0300

4.       The time zone displayed in the result field is expected to change, but the time zone does not change.

Based on glibc, execute the same test code and steps. The running result is as follows:

result: 2023-02-11T10:46:41+0800
result: 2023-02-11T10:47:01+0800
result: 2023-02-11T05:47:21+0300
result: 2023-02-11T05:47:41+0300

I found the problem is caused by the do_tzset function.
The global variable old_tz caches the string that describes the time zone when the time zone is updated last time. The value of the string can be the value of the TZ environment variable, ¡°/etc/localtime¡±, or ¡°UTC¡±. If the current string describing the time zone is the same as the cached value, the time zone will not be updated.
Therefore, when the cached value is ¡°/etc/localtime¡±, the time zone is not updated even though the time zone file linked to ¡°/etc/localtime¡± changes.

The ¡°/etc/localtime¡± describes the file path instead of the time zone. I suggest not storing it to old_tz. The related code is as follows:

static void do_tzset()
{
        char buf[NAME_MAX+25], *pathname=buf+24;
        const char *try, *s, *p;
        const unsigned char *map = 0;
        size_t i;
        static const char search[] =
               "/usr/share/zoneinfo/\0/share/zoneinfo/\0/etc/zoneinfo/\0";

        s = getenv("TZ");
        if (!s) s = "/etc/localtime";
        if (!*s) s = __utc;

        if (old_tz && !strcmp(s, old_tz)) return;

        for (i=0; i<5; i++) r0[i] = r1[i] = 0;

        if (zi) __munmap((void *)zi, map_size);

        /* Cache the old value of TZ to check if it has changed. Avoid
        * free so as not to pull it into static programs. Growth
        * strategy makes it so free would have minimal benefit anyway. */
        i = strlen(s);
        if (i > PATH_MAX+1) s = __utc, i = 3;
        if (i >= old_tz_size) {
               old_tz_size *= 2;
               if (i >= old_tz_size) old_tz_size = i+1;
               if (old_tz_size > PATH_MAX+2) old_tz_size = PATH_MAX+2;
               old_tz = malloc(old_tz_size);
        }
        if (old_tz) memcpy(old_tz, s, i+1);
        ¡­
}

[-- Attachment #2: Type: text/html, Size: 16797 bytes --]

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [musl] Time zone has not updated after call tzset()
  2023-02-11  6:53 [musl] Time zone has not updated after call tzset() zhoujingqiang (A)
@ 2023-02-11 14:10 ` alice
  2023-02-11 14:20   ` Rich Felker
  0 siblings, 1 reply; 5+ messages in thread
From: alice @ 2023-02-11 14:10 UTC (permalink / raw)
  To: musl
  Cc: yubing (C), liudongxu, wangyunhe (A), qiuguorui, Wanglieming (VRP SSP)

On Sat Feb 11, 2023 at 7:53 AM CET, zhoujingqiang (A) wrote:
> Hello,
>
> Normally, /etc/localtime is a soft link to a file that stores time zone
> information.
>
> Without setting the TZ environment variable, I change the time zone by
> changing the file linked to /etc/localtime. After calling tzset(), I find that
> the time zone does not change. The test code is as follows:

musl does not support changing the timezone while running.
see https://www.openwall.com/lists/musl/2017/06/09/9 ,
for a response to an identical bug report

tl;dr without semantics: you have to restart a running process to get a new
timezone.

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [musl] Time zone has not updated after call tzset()
  2023-02-11 14:10 ` alice
@ 2023-02-11 14:20   ` Rich Felker
  2023-02-11 14:30     ` alice
  0 siblings, 1 reply; 5+ messages in thread
From: Rich Felker @ 2023-02-11 14:20 UTC (permalink / raw)
  To: alice
  Cc: musl, yubing (C), liudongxu, wangyunhe (A),
	qiuguorui, Wanglieming (VRP SSP)

On Sat, Feb 11, 2023 at 03:10:40PM +0100, alice wrote:
> On Sat Feb 11, 2023 at 7:53 AM CET, zhoujingqiang (A) wrote:
> > Hello,
> >
> > Normally, /etc/localtime is a soft link to a file that stores time zone
> > information.
> >
> > Without setting the TZ environment variable, I change the time zone by
> > changing the file linked to /etc/localtime. After calling tzset(), I find that
> > the time zone does not change. The test code is as follows:
> 
> musl does not support changing the timezone while running.
> see https://www.openwall.com/lists/musl/2017/06/09/9 ,
> for a response to an identical bug report
> 
> tl;dr without semantics: you have to restart a running process to get a new
> timezone.

This is not quite accurate. It does, but only via application intent,
in the form of changing its value of TZ. It does not re-scan files if
the application doesn't do that, for two important reasons:

1. Without explicit action by the application, there is no way to
   synchronize changes to the timezone with application consumption of
   the timezone. Operations like localtime, [some adjustment], mktime
   will give erroneous results under a race where the zone changes
   between the calls. (One might suggest using calls to tzset to
   synchronize, but POSIX specifies that all the functions which use
   time zone behave as if they implicitly called tzset, so this seems
   to be forbidden, and it wouldn't be thread-safe anyway.)

2. Re-scanning the file on disk every time an operation using the time
   zone is performed results in abysmal performance. This is a
   bottleneck for lots of programs that do any kind of logging, and if
   I recall it was the topic of a longstanding, user-infuriating bug
   report against glibc.

Rich

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [musl] Time zone has not updated after call tzset()
  2023-02-11 14:20   ` Rich Felker
@ 2023-02-11 14:30     ` alice
  2023-02-11 14:42       ` Rich Felker
  0 siblings, 1 reply; 5+ messages in thread
From: alice @ 2023-02-11 14:30 UTC (permalink / raw)
  To: Rich Felker
  Cc: musl, yubing (C), liudongxu, wangyunhe (A),
	qiuguorui, Wanglieming (VRP SSP)

On Sat Feb 11, 2023 at 3:20 PM CET, Rich Felker wrote:
> On Sat, Feb 11, 2023 at 03:10:40PM +0100, alice wrote:
> > On Sat Feb 11, 2023 at 7:53 AM CET, zhoujingqiang (A) wrote:
> > > Hello,
> > >
> > > Normally, /etc/localtime is a soft link to a file that stores time zone
> > > information.
> > >
> > > Without setting the TZ environment variable, I change the time zone by
> > > changing the file linked to /etc/localtime. After calling tzset(), I find that
> > > the time zone does not change. The test code is as follows:
> > 
> > musl does not support changing the timezone while running.
> > see https://www.openwall.com/lists/musl/2017/06/09/9 ,
> > for a response to an identical bug report
> > 
> > tl;dr without semantics: you have to restart a running process to get a new
> > timezone.
>
> This is not quite accurate. It does, but only via application intent,
> in the form of changing its value of TZ. It does not re-scan files if
> the application doesn't do that, for two important reasons:

yes, with the semantics, something like:

 setenv("TZ", "something", 0);
 tzset();
 unsetenv("TZ");

will update to a new /etc/localtime symlink. it's mentioned in
https://marc.info/?l=musl&m=141374003126007&w=2
from the above thread.

(apologies, i worded that poorly; what i mean is you cannot rely on /
etc/localtime being read on update (without the hack above), which was the
question. setenv("TZ") is also supported, of course.)

> 1. Without explicit action by the application, there is no way to
>    synchronize changes to the timezone with application consumption of
>    the timezone. Operations like localtime, [some adjustment], mktime
>    will give erroneous results under a race where the zone changes
>    between the calls. (One might suggest using calls to tzset to
>    synchronize, but POSIX specifies that all the functions which use
>    time zone behave as if they implicitly called tzset, so this seems
>    to be forbidden, and it wouldn't be thread-safe anyway.)
>
> 2. Re-scanning the file on disk every time an operation using the time
>    zone is performed results in abysmal performance. This is a
>    bottleneck for lots of programs that do any kind of logging, and if
>    I recall it was the topic of a longstanding, user-infuriating bug
>    report against glibc.
>
> Rich


^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [musl] Time zone has not updated after call tzset()
  2023-02-11 14:30     ` alice
@ 2023-02-11 14:42       ` Rich Felker
  0 siblings, 0 replies; 5+ messages in thread
From: Rich Felker @ 2023-02-11 14:42 UTC (permalink / raw)
  To: alice
  Cc: musl, yubing (C), liudongxu, wangyunhe (A),
	qiuguorui, Wanglieming (VRP SSP)

On Sat, Feb 11, 2023 at 03:30:58PM +0100, alice wrote:
> On Sat Feb 11, 2023 at 3:20 PM CET, Rich Felker wrote:
> > On Sat, Feb 11, 2023 at 03:10:40PM +0100, alice wrote:
> > > On Sat Feb 11, 2023 at 7:53 AM CET, zhoujingqiang (A) wrote:
> > > > Hello,
> > > >
> > > > Normally, /etc/localtime is a soft link to a file that stores time zone
> > > > information.
> > > >
> > > > Without setting the TZ environment variable, I change the time zone by
> > > > changing the file linked to /etc/localtime. After calling tzset(), I find that
> > > > the time zone does not change. The test code is as follows:
> > > 
> > > musl does not support changing the timezone while running.
> > > see https://www.openwall.com/lists/musl/2017/06/09/9 ,
> > > for a response to an identical bug report
> > > 
> > > tl;dr without semantics: you have to restart a running process to get a new
> > > timezone.
> >
> > This is not quite accurate. It does, but only via application intent,
> > in the form of changing its value of TZ. It does not re-scan files if
> > the application doesn't do that, for two important reasons:
> 
> yes, with the semantics, something like:
> 
>  setenv("TZ", "something", 0);
>  tzset();
>  unsetenv("TZ");
> 
> will update to a new /etc/localtime symlink. it's mentioned in
> https://marc.info/?l=musl&m=141374003126007&w=2
> from the above thread.
> 
> (apologies, i worded that poorly; what i mean is you cannot rely on /
> etc/localtime being read on update (without the hack above), which was the
> question. setenv("TZ") is also supported, of course.)

One small note: if you unsetenv afterwards like that, you'll never get
to use the newly selected zone since the next tz-using operation will
implicitly perform another tzset (as required by POSIX).

Rich

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2023-02-11 14:42 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-02-11  6:53 [musl] Time zone has not updated after call tzset() zhoujingqiang (A)
2023-02-11 14:10 ` alice
2023-02-11 14:20   ` Rich Felker
2023-02-11 14:30     ` alice
2023-02-11 14:42       ` Rich Felker

Code repositories for project(s) associated with this public inbox

	https://git.vuxu.org/mirror/musl/

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 NNTP newsgroup(s).