mailing list of musl libc
 help / color / mirror / code / Atom feed
From: "zhoujingqiang (A)" <zhoujingqiang1@huawei.com>
To: "musl@lists.openwall.com" <musl@lists.openwall.com>
Cc: "yubing (C)" <yubing12@huawei.com>,
	liudongxu <liudongxu3@huawei.com>,
	"wangyunhe (A)" <wangyunhe@huawei.com>,
	qiuguorui <qiuguorui1@huawei.com>,
	"Wanglieming (VRP SSP)" <wanglieming@huawei.com>
Subject: [musl] Time zone has not updated after call tzset()
Date: Sat, 11 Feb 2023 06:53:38 +0000	[thread overview]
Message-ID: <f875523c2c094e2db64cbcd13aace527@huawei.com> (raw)

[-- 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 --]

             reply	other threads:[~2023-02-11 14:03 UTC|newest]

Thread overview: 5+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-02-11  6:53 zhoujingqiang (A) [this message]
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

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:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

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

  git send-email \
    --in-reply-to=f875523c2c094e2db64cbcd13aace527@huawei.com \
    --to=zhoujingqiang1@huawei.com \
    --cc=liudongxu3@huawei.com \
    --cc=musl@lists.openwall.com \
    --cc=qiuguorui1@huawei.com \
    --cc=wanglieming@huawei.com \
    --cc=wangyunhe@huawei.com \
    --cc=yubing12@huawei.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* 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.
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).