这个问题困扰了我很久,原因有二:
1、程序不是个单文件脚本
2、单元测试无法重现错误
后来在同事的帮助下,总算找到了问题所在
localtime(3) calls tzset(3), but localtime_r(3) not.
threaded perl localtime() calls localtime_r(3) instead of localtime(3)
来看一下 Date::Simple 的一段源代码
sub format {
my ($self,$format)=@_;
$format= $fmts{refaddr($self)||''} || $fmts{ref($self)} || $Standard_Format
if @_==1;
return "$self" unless defined ($format);
require POSIX;
local $ENV{TZ} = 'UTC+0';
return POSIX::strftime ($format, _gmtime ($self));
}
POSIX::strftime() 调用 tzset() 时看到的环境变量 $ENV{TZ} 是 UTC+0。在这之后就有问题了,如果使用 localtime(),因为 localtime_r(3) 并不会调用 tzset(),所以即使环境变量 $ENV{TZ} 已经恢复原值,localtime() 查看内部变量的时候,还是之前的 UTC+0。
至于为什么 localtime_r(3) 不像 localtime(3) 一样调用 tzset(3) 根据环境变量重设时区,我理解下来的主要原因是因为,它是线程不安全的。可能会出现下面这种情况
thread1
thread2
tzset()
tzset()
localtime()
localtime()
另外,关于环境变量 $ENV{TZ}存在(exists),但其值为空的时候,也会得到 UTC+0 的结果。
相关链接:
perlbug #26136
No comments:
Post a Comment