glibc 在 localtime_r 和 TZ 方面的行为是否符合 posix

问题描述 投票:0回答:1

我正在移植一些代码以使用

localtime_r
而不是
localtime
来使其更加线程安全,但在
localtime
localtime_r
之间遇到了一个非常有趣的区别,这对我来说似乎是难以理解的如果 glibc 的行为符合要求,则 glic
ctime(3)
手册页和
localtime_r
的 posix 规范(我至少觉得它非常令人惊讶,但这当然并不意味着它是一个错误)。

我的程序如下:

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

int main() {
    time_t t;
    struct tm u;

    time(&t);

    localtime_r(&t, &u);
    // u = *localtime(&t);
    printf("%ld\n", u.tm_gmtoff);

    setenv("TZ", "UTC+2", 1);
    localtime_r(&t, &u);
    // u = *localtime(&t);
    printf("%ld\n", u.tm_gmtoff);

    tzset();
    localtime_r(&t, &u);
    // u = *localtime(&t);
    printf("%ld\n", u.tm_gmtoff);
}

在我的时区(山地时间),此打印

-25200
-25200
-7200

如果我用注释掉的

localtime_r
调用替换所有
localtime
调用,我得到

-25200
-7200
-7200

查看glibc源代码,

localtime_r
tzset_internal
调用
always=0
,这意味着如果
TZ
尚未被调用,它只会读取
tzset_internal
环境变量。

标准说(来自https://pubs.opengroup.org/onlinepubs/9699919799/functions/localtime.html):

使用本地时区信息就像 localtime() 调用 tzset() 一样。

(并且

tzset
确实需要阅读
TZ
)。然后后来,

与 localtime() 不同,localtime_r() 函数不需要设置 tzname。如果 localtime_r() 设置 tzname,它还应设置日光和时区。如果 localtime_r() 没有设置 tzname,则不会设置日光,也不会设置时区。

glibc 手册页也说了几乎同样的事情。

这对我来说似乎有点不清楚是否需要

localtime_r
来读取更新的
TZ
值。
localtime
肯定是,而且我知道读取
TZ
和设置
tzname
可能通常在实现中耦合,但从规范的角度来看,我会假设没有具体提及
localtime_r
就可以不读取
TZ 
,它应该遵循
localtime
行为。

那么,这是错误还是只是令人惊讶但在其他方面合规的行为?如果我希望它们具有与

tzset()
相同的行为,我是否应该考虑在
localtime_r
调用之前调用
localtime

c timezone posix glibc
1个回答
0
投票

localtime_r()
不应该修改任何静态数据。
tzset()
使用静态数据来保存时区信息。所以
localtime_r()
不会调用它,或者做相当于调用它的事情。

它可以检查 TZ 环境变量并将时区信息存储在调用的本地数据中。但是,对每次调用执行此操作对性能的影响将是巨大的,而 POSIX 并不需要这样做。在

localtime_r()
的描述中,没有任何地方说它的行为就像在内部使用
tzset()

最好有一个

tzset_r()
函数用时区信息填充给定的数据结构(我建议它应该将时区名称作为参数,而不是使用环境变量),并且这可以传递给
localtime_r()
。但他们不是这么指定的。

© www.soinside.com 2019 - 2024. All rights reserved.