为什么gmtime_r调用__tz_convert来获取全局锁?

时间:2018-12-21 18:05:15

标签: c glibc libc

我很惊讶地看到gmtime_r真的在呼叫tz-任何东西。我认为存在本地时间vs gmtime的原因是前者可以进行tz转换,而后者则不需要。看起来gmtime会调用__tz_convert,然后继续并在tz上获取全局锁(甚至根本不需要...对吗?) 我在这里想念什么吗? 如何在多线程应用程序中高效地转换epoch-> struct tm?

(gdb) where
#0  0x00007fffee255eec in __lll_lock_wait_private () from /lib64/libc.so.6
#1  0x00007fffee2007bc in _L_lock_2546 () from /lib64/libc.so.6
#2  0x00007fffee2005f7 in __tz_convert () from /lib64/libc.so.6
#3  0x000000000041c63f in DateTimeEx (dt=..., this=0x7fffca551900) at /var/lib/jenkins/workspace/hfalgo_src_hotfix_1.69.1-T6J4HNFQDMYVEKV4MEGVD6UCCPG7KHWQDOSVYBUDROFXZA6YINSA/hfalgo_src/./core/Time.h:81

1 个答案:

答案 0 :(得分:1)

glibc可以处理包含leap秒信息的时区数据库文件,并且gmtimegmtime_r会考虑这些leap秒。 (例如,Debian tzdata软件包在/usr/share/zoneinfo/right目录中提供了此类时区文件。)这就是为什么glibc实现读取时区数据库并执行与此相关的一些锁定的原因。

我不知道有人实际使用the秒功能。 POSIX当前要求从纪元开始的计数不考虑任何leap秒,因此,使用带有leap秒的数据文件会导致诸如gmtime之类的功能出现不一致的行为。

但是,我希望某些不可移植的软件依赖于这样的事实,即调用gmtimegmtime_r会执行隐式tzset调用,从而初始化tzname和其他全局变量变量。这是从当前实现中消除锁定的更大障碍。 (有人甚至为此悬赏,但100美元的价格与解决此问题所需的努力完全不成比例。)

如果您今天需要避免锁定,则需要查找gmtime算法(日历计算是这些问题的有趣参考)并自行实现。