操作
Y2038¶
Y2038:lighttpd 1.4.60 及更高版本报告 Y2038 安全性¶
$ lighttpd -V + Y2038 support # Y2038-SAFE $ lighttpd -V - Y2038 support (unsafe 32-bit signed time_t) # Y2038-UNSAFE
Y2038:通用平台信息¶
- Y2038-安全:lighttpd 64位构建在使用了 64位 time_t 的平台上
- 所有主要的 64 位平台(据本文作者所知)都使用 64 位 time_t
- Y2038-安全:lighttpd 32位构建在使用了 64位 time_t 的平台上
- Linux x32 ABI(不同于 i686)
- FreeBSD 所有 32 位和 64 位架构,除了 32 位 i386
- NetBSD 6.0(2012年10月发布)所有 32 位和 64 位架构
- OpenBSD 5.5(2014年5月发布)所有 32 位和 64 位架构
- Microsoft Windows XP 和 Visual Studio 2005(?不确定?)
另一份参考资料表明 Visual Studio 2015 默认使用 64 位 time_t - MacOS 10.15 Catalina(2019年发布)放弃了对 32 位应用程序的支持
- Y2038-安全:lighttpd 32位构建在使用了 32位无符号 time_t 的平台上
- 例如 OpenVMS(Lighttpd 是否能在此平台上构建尚不清楚)
- Y2038-不安全:lighttpd 32位构建在使用了 32位有符号 time_t 的平台上
- Linux 32 位(包括 i686)
- glibc 32 位库对 64 位 time_t 的支持尚未可用
- https://sourceware.org/glibc/wiki/Y2038ProofnessDesign
- Linux 内核 5.6 在 32 位平台上确实支持 64 位 time_t
https://itsubuntu.com/linux-kernel-5-6-to-fix-the-year-2038-issue-unix-y2k/
- https://gnu.ac.cn/software/libc/manual/html_node/64_002dbit-time-symbol-handling.html
"注意:目前,双时间配置中的 64 位时间支持仍在进行中,因此对于这些配置,公共 API 仅提供 32 位时间支持。在后续的更改中,公共 API 将允许用户代码为给定的编译单元选择时间大小。"
- 使用 -D_TIME_BITS=64 进行编译目前没有效果 - glibc 最近(2021年7月)的邮件列表讨论
- https://public-inbox.org/bug-gnulib/878s2ozq70.fsf@oldenburg.str.redhat.com/T/ - glibc master 分支包含一些针对 -D_TIME_BITS=64 的提交
- https://www.phoronix.com/scan.php?page=news_item&px=Glibc-More-Y2038-Work
- glibc 32 位库对 64 位 time_t 的支持尚未可用
- FreeBSD i386
- DragonFlyBSD 32 位
- Linux 32 位(包括 i686)
Y2038:在 Y2038-不安全平台(32 位有符号 time_t)上尝试的缓解措施¶
- 在不需要实时时钟的地方,lighttpd 优先使用系统单调时钟而非实时时钟
- lighttpd 将负的 time_t 值视为 2038 年 1 月 19 日 03:14:07 GMT 之后的时间
(lighttpd 假定在正常操作期间不会遇到 1970 年之前的日期。) - lighttpd 将 struct stat st.st_mtime(和 st.st_*time)通过 uint64_t 进行类型转换,以将负时间戳转换为 64 位时间戳进行比较
(将负时间戳值视为 2038 年 1 月 19 日 03:14:07 GMT 之后的时间) - lighttpd 提供 unix_time64_t (int64_t) 和
- lighttpd 提供 struct unix_timespec64 (unix_timespec64_t)
(使用 unix_time64_t tv_sec 成员的 struct timespec 等效项) - lighttpd 为使用 32 位 time_t 的 32 位平台提供了 gmtime64_r() 和 localtime64_r() 封装,并且 lighttpd 临时调整年份,以便使用标准库中的 gmtime_r() 和 localtime_r()(或 gmtime() 和 localtime()),之后再重新调整年份并将 struct tm 传递给 strftime() 等格式化函数
- lighttpd 提供 TIME64_CAST() 宏,用于将有符号 32 位 time_t 转换为无符号 32 位,然后再转换为 unix_time64_t
Y2038:警告¶
注意:尽管 lighttpd 尝试在使用了 32 位有符号 time_t 的 32 位平台上处理 2038 年 1 月 19 日 03:14:07 GMT 之后的时间,但在 32 位有符号 time_t 溢出(2038 年 1 月 19 日 03:14:08 GMT)之后,底层库和底层文件系统可能无法正常运行。如果某个 32 位操作系统在使用负 time_t 值时无法正常工作,那么 lighttpd 在该系统上也可能无法正常工作。
Y2038:其他参考资料和博客¶
https://en.wikipedia.org/wiki/Year_2038_problem
https://en.wikipedia.org/wiki/Time_formatting_and_storage_bugs
http://www.lieberbiber.de/2017/03/14/a-look-at-the-year-20362038-problems-and-time-proofness-in-various-systems/