Description of problem: 将硬件时钟设置为 '2038-01-19 03:14:08 UTC', 报错: hwclock: settimeofday() 失败: 无效的参数. Version-Release number of selected component (if applicable): Anolis OS release 8.9 How reproducible: 在默认的系统环境下. Steps to Reproduce: 1.进入系统, 在终端依次执行下面的命令: /usr/bin/timedatectl set-timezone Asia/Shanghai sudo /usr/sbin/hwclock --set --date '2038-01-19 03:14:08 UTC' sudo /usr/sbin/hwclock --hctosys 2.观察终端执行指令后的回显日志, [songcy@anolis ~]$ sudo /usr/sbin/hwclock --hctosys hwclock: settimeofday() 失败: 无效的参数 [songcy@anolis ~]$ [songcy@anolis ~]$ date 2025年 02月 11日 星期二 14:47:18 CST [songcy@anolis ~]$ Actual results: 设置系统时钟失败, date 回显时间不符合设置的预期. Expected results: 1.通过 系统工具 hwclock 设置系统时钟为 '2038-01-19 03:14:08 UTC'不报错, 2.执行指令 'date' 回显时间 符合设置的时间预期 Additional info: 无
补充一下信息, [songcy@anolis ~]$ sudo /usr/sbin/hwclock --set --date '2037-01-19 03:14:08 UTC' [songcy@anolis ~]$ sudo /usr/sbin/hwclock --hctosys [songcy@anolis ~]$ date 2037年 01月 19日 星期一 11:14:14 CST [songcy@anolis ~]$ [songcy@anolis ~]$ sudo /usr/sbin/hwclock --set --date '2038-01-19 03:14:08 UTC' [songcy@anolis ~]$ sudo /usr/sbin/hwclock --hctosys hwclock: settimeofday() 失败: 无效的参数 [songcy@anolis ~]$ 注意: 设置 系统时间为 '2037-01-19 03:14:08 UTC', 没有执行报错, 下面是问题相关的参考链接: [1] https://askubuntu.com/questions/299475/will-the-linux-clock-fail-at-january-19-2038-31408 [2] http://painterengineering.com/pei_unixtime.pdf [3] https://www.zhihu.com/question/432241505
1)设置为 2037 年时,成功。 # /usr/sbin/hwclock --set --date '2037-01-19 03:14:08 UTC' # /usr/sbin/hwclock --hctosys # bpftrace settimeofday.bt Attaching 2 probes... do_sys_settimeofday64 comm:hwclock, timespec64: sec=0x0 nsec=0x0, timezone: tz_minuteswest=0 tz_dsttime=0 do_sys_settimeofday64 retval is=0 do_sys_settimeofday64 comm:hwclock, timespec64: sec=0x0 nsec=0x0, timezone: tz_minuteswest=-480 tz_dsttime=0 do_sys_settimeofday64 retval is=0 do_sys_settimeofday64 comm:hwclock, timespec64: sec=0x7e1ecc86 nsec=0x0, timezone: tz_minuteswest=0 tz_dsttime=0 do_sys_settimeofday64 retval is=0 syscall调用栈信息: @[ do_sys_settimeofday64+1 __x64_sys_clock_settime+104 do_syscall_64+49 entry_SYSCALL_64_after_hwframe+98 ]: 1 @[ do_sys_settimeofday64+1 __x64_sys_settimeofday+129 do_syscall_64+49 entry_SYSCALL_64_after_hwframe+98 ]: 2 2)设置为 2038年时,失败。 发现 hwclock 没有下发第3次 syscall clock_settime(CLOCK_REALTIME, ...); # /usr/sbin/hwclock --set --date '2038-01-19 03:14:08 UTC' # /usr/sbin/hwclock --hctosys hwclock: settimeofday() 失败: 无效的参数 # bpftrace settimeofday.bt Attaching 2 probes... do_sys_settimeofday64 comm:hwclock, timespec64: sec=0x0 nsec=0x0, timezone: tz_minuteswest=0 tz_dsttime=0 do_sys_settimeofday64 retval is=0 do_sys_settimeofday64 comm:hwclock, timespec64: sec=0x0 nsec=0x0, timezone: tz_minuteswest=-480 tz_dsttime=0 do_sys_settimeofday64 retval is=0 syscall调用栈信息: @[ do_sys_settimeofday64+1 __x64_sys_settimeofday+129 do_syscall_64+49 entry_SYSCALL_64_after_hwframe+98 ]: 2 因此,不是内核的问题,是hwclock程序的实现逻辑哪里有问题,内核已经可以正确处理year-2038问题(例如执行date -s '2038-01-19 03:14:08 UTC' 可以成功),看起来是hwclock工具没有解决 y2038 问题。
From chatgpt:hwclock 哪个版本解决了 2038 问题? 2038 问题是指在使用 32 位时间戳的系统中,时间表示的最大值为 2038 年 1 月 19 日 03:14:07 UTC。超过这个时间点后,时间戳会溢出并导致系统错误。为了解决这个问题,需要使用 64 位时间戳。 hwclock 是一个用于读取和设置硬件时钟(RTC)的工具。为了支持 64 位时间戳并解决 2038 问题,hwclock 需要进行相应的更新。以下是一些相关信息: hwclock 的版本历史 hwclock 从 util-linux 2.32 版本开始: util-linux 2.32 及更高版本中的 hwclock 工具引入了对 64 位时间戳的支持,从而解决了 2038 问题。 在这些版本中,hwclock 使用 64 位时间戳来处理时间和日期,确保在 2038 年之后的时间也能正确处理。 检查 util-linux 版本 你可以通过以下命令检查当前系统上安装的 util-linux 版本: util-linux --version
(In reply to xunlei from comment #3) > From chatgpt:hwclock 哪个版本解决了 2038 问题? > 2038 问题是指在使用 32 位时间戳的系统中,时间表示的最大值为 2038 年 1 月 19 日 03:14:07 > UTC。超过这个时间点后,时间戳会溢出并导致系统错误。为了解决这个问题,需要使用 64 位时间戳。 > > hwclock 是一个用于读取和设置硬件时钟(RTC)的工具。为了支持 64 位时间戳并解决 2038 问题,hwclock > 需要进行相应的更新。以下是一些相关信息: > > hwclock 的版本历史 > hwclock 从 util-linux 2.32 版本开始: > util-linux 2.32 及更高版本中的 hwclock 工具引入了对 64 位时间戳的支持,从而解决了 2038 问题。 > 在这些版本中,hwclock 使用 64 位时间戳来处理时间和日期,确保在 2038 年之后的时间也能正确处理。 > 检查 util-linux 版本 > 你可以通过以下命令检查当前系统上安装的 util-linux 版本: > util-linux --version rpm -q util-linux
(In reply to xunlei from comment #4) 提单的问题场景 环境是 util-linux-2.32.1-43.0.1.an8.x86_64, [songcy@anolis ~]$ rpm -qf $(which hwclock) util-linux-2.32.1-43.0.1.an8.x86_64 [songcy@anolis ~]$ rpm -q util-linux util-linux-2.32.1-43.0.1.an8.x86_64 [songcy@anolis ~]$ 继续更新工具 util-linux 到最新版本, 问题复现, [songcy@anolis ~]$ yum --showduplicates list util-linux AnolisOS-8 - Extras 9.5 kB/s | 2.3 kB 00:00 Extra Packages for Enterprise Linux Modular 8 - x86_64 6.7 kB/s | 733 kB 01:49 已安装的软件包 util-linux.x86_64 2.32.1-43.0.1.an8 @anaconda 可安装的软件包 util-linux.x86_64 2.32.1-43.0.1.an8 BaseOS util-linux.x86_64 2.32.1-44.0.1.an8.1 BaseOS util-linux.x86_64 2.32.1-45.0.1.an8.1 BaseOS util-linux.x86_64 2.32.1-46.0.1.an8 BaseOS util-linux.x86_64 2.32.1-46.0.3.an8 BaseOS [songcy@anolis ~]$ [songcy@anolis ~]$ sudo yum install util-linux-2.32.1-46.0.3.an8 ... 已升级: libblkid-2.32.1-46.0.3.an8.x86_64 libfdisk-2.32.1-46.0.3.an8.x86_64 libmount-2.32.1-46.0.3.an8.x86_64 libsmartcols-2.32.1-46.0.3.an8.x86_64 libuuid-2.32.1-46.0.3.an8.x86_64 util-linux-2.32.1-46.0.3.an8.x86_64 util-linux-user-2.32.1-46.0.3.an8.x86_64 完毕! [songcy@anolis ~]$ [songcy@anolis ~]$ rpm -qf $(which hwclock) util-linux-2.32.1-46.0.3.an8.x86_64 [songcy@anolis ~]$ rpm -q util-linux util-linux-2.32.1-46.0.3.an8.x86_64 [songcy@anolis ~]$ hwclock,来自 util-linux 2.32.1 [songcy@anolis ~]$ [songcy@anolis ~]$ sudo /usr/sbin/hwclock --set --date '2038-01-19 03:14:08 UTC' [songcy@anolis ~]$ sudo /usr/sbin/hwclock --hctosys hwclock: settimeofday() 失败: 无效的参数 [songcy@anolis ~]$
Created attachment 1298 [details] 去掉 (int) 强转, 问题不复现了,
Dear xunlei, 我们在 gdb 调试 hwclock 的时候, 找到了问题点, 通过修改源码后重编译, "2038 年" 的问题得到了解决, 报错的问题不再复现. 具体修改内容如下: static struct timeval time_inc(struct timeval addend, double increment) { struct timeval newtime; // newtime.tv_sec = addend.tv_sec + (int)increment; newtime.tv_sec = addend.tv_sec + increment; // newtime.tv_usec = addend.tv_usec + (increment - (int)increment) * 1E6; newtime.tv_usec = addend.tv_usec + (increment - increment) * 1E6; 修改后重新编译 hwclock, 执行指令的现象如下: [songcy@anolis util-linux-2.32.1]$ sudo ./hwclock --set --date '2038-01-19 03:14:08 UTC' [sudo] songcy 的密码: [songcy@anolis util-linux-2.32.1]$ [songcy@anolis util-linux-2.32.1]$ sudo ./hwclock --hctosys [songcy@anolis util-linux-2.32.1]$ date 2038年 01月 19日 星期二 11:14:16 CST [songcy@anolis util-linux-2.32.1]$ 注: 从结果来看, "2038 问题" 的报错 没有复现了, 下面是我的定位问题的具体步骤, 可以按需参考一下, 1. 首先需要获取到 当前版本工具的源码, 重新编译出可供调试的二进制程序, 837 rpm -qf $(which hwclock) # 查询当前系统中工具的版本号 838 yum --showduplicates list util-linux # 查询当前支持的版本号, 需要下载当前版本匹配的源码包 843 yumdownloader --source util-linux-2.32.1-46.0.3.an8.x86_64 # 下载源码包 844 ls -lrt 845 mkdir util-linux-2.32.1-46.0.3.an8.src 846 cp util-linux-2.32.1-46.0.3.an8.src.rpm util-linux-2.32.1-46.0.3.an8.src 847 cd util-linux-2.32.1-46.0.3.an8.src 849 rpm2cpio util-linux-2.32.1-46.0.3.an8.src.rpm | cpio -idv # 解压 rpm 包 850 ls -lrt | grep -v ".patch" 851 tar -xf util-linux-2.32.1.tar.xz 852 ls -lrt | grep -v ".patch" 853 cd util-linux-2.32.1/ 854 ./configure --disable-all-programs --enable-hwclock --enable-debug # 只编译 hwclock,避免编译整个 util-linux 858 grep "^CFLAGS \= " Makefile 859 vim Makefile ==> 修改一下 CFLAGS = -g3 -O0 # 禁用优化 并 启用完整的调试信息 861 make -j$(nproc) 862 ls -lrt 863 sudo gdb ./hwclock 2.然后 gdb 调试 hwclock (gdb) run --set --date '2038-01-19 03:14:08 UTC' Starting program: /home/songcy/proj_repositories/util-linux-2.32.1-43.0.1.an8.src/util-linux-2.32.1/tmp/util-linux-2.32.1-46.0.3.an8.src/util-linux-2.32.1/hwclock --set --date '2038-01-19 03:14:08 UTC' [Inferior 1 (process 309703) exited normally] (gdb) source /home/songcy/proj_repositories/my-work-place/hwclock_gdb_breakpoints.txt Breakpoint 1 at 0x402ad1: file sys-utils/hwclock.c, line 370. Breakpoint 2 at 0x404354: file sys-utils/hwclock.c, line 1103. Breakpoint 3 at 0x403ac0: file sys-utils/hwclock.c, line 907. Breakpoint 4 at 0x4053eb: file sys-utils/hwclock-rtc.c, line 158. Breakpoint 5 at 0x40297d: file sys-utils/hwclock.c, line 328. Breakpoint 6 at 0x7ffff74eba70 Breakpoint 7 at 0x403dc0: file sys-utils/hwclock.c, line 981. Breakpoint 8 at 0x40311b: file sys-utils/hwclock.c, line 617. (gdb) info breakpoints Num Type Disp Enb Address What 1 breakpoint keep n 0x0000000000402ad1 in read_hardware_clock at sys-utils/hwclock.c:370 2 breakpoint keep n 0x0000000000404354 in main at sys-utils/hwclock.c:1103 3 breakpoint keep n 0x0000000000403ac0 in manipulate_clock at sys-utils/hwclock.c:907 4 breakpoint keep n 0x00000000004053eb in do_rtc_read_ioctl at sys-utils/hwclock-rtc.c:158 5 breakpoint keep n 0x000000000040297d in mktime_tz at sys-utils/hwclock.c:328 6 breakpoint keep n 0x00007ffff74eba70 <timegm> 7 breakpoint keep y 0x0000000000403dc0 in manipulate_clock at sys-utils/hwclock.c:981 8 breakpoint keep y 0x000000000040311b in set_system_clock at sys-utils/hwclock.c:617 (gdb) run --hctosys Starting program: /home/songcy/proj_repositories/util-linux-2.32.1-43.0.1.an8.src/util-linux-2.32.1/tmp/util-linux-2.32.1-46.0.3.an8.src/util-linux-2.32.1/hwclock --hctosys Breakpoint 7, manipulate_clock (ctl=0x7fffffffe250, set_time=0, startup_time=..., adjtime=0x7fffffffe210) at sys-utils/hwclock.c:981 981 if (!ctl->show) (gdb) bt #0 manipulate_clock (ctl=0x7fffffffe250, set_time=0, startup_time=..., adjtime=0x7fffffffe210) at sys-utils/hwclock.c:981 #1 0x0000000000404957 in main (argc=0, argv=0x7fffffffe368) at sys-utils/hwclock.c:1363 (gdb) list 976 */ 977 calculate_adjustment(ctl, adjtime->drift_factor, 978 adjtime->last_adj_time, 979 adjtime->not_adjusted, 980 hclocktime.tv_sec, &tdrift); 981 if (!ctl->show) 982 hclocktime = time_inc(tdrift, hclocktime.tv_sec); 983 984 startup_hclocktime = 985 time_inc(hclocktime, time_diff(startup_time, read_time)); (gdb) 注意: 上面是我调试使用到的断点, 重点关注 断点 7 和 8, 这两个点 会定位到问题, 问题现象是 hclocktime.tv_sec 转变成了 负数, hclocktime.tv_usec 值不为 0, 下一步: 请 check 一下 方法 time_inc 的代码修改, 我对源码的设计原理不理解, 这么粗暴的修改预期会存在问题.
Created attachment 1299 [details] 去掉 (int) 强转, 问题不复现了
(In reply to xunlei from comment #2) Dear Xunlei, 按照你前面所述, 当前这个问题 最直接的表现是 hwclock 用户态工具的代码逻辑问题, 这个问题 应该找哪位 ower 来支撑? 或者帮忙内部交接一下呢?
https://github.com/util-linux/util-linux/pull/1294 上游的讨论。
构建完成,待发布 http://build.openanolis.cn/buildinfo?buildID=38895
(In reply to Weisson from comment #11) > 构建完成,待发布 http://build.openanolis.cn/buildinfo?buildID=38895 Dear Weisson, 我正在关注 如何应用当前问题的解决方案 到我们的项目上. 1. 关于应用你的修复方案, 首先我能想到的是 直接 install 修复问题后的 rpm 包, 我没有看到 "2.23.1-46.0.4" 版本的发布, 我在哪里可以找到这个版本? [songcy@anolis proj_repositories]$ rpm -qf $(which hwclock) util-linux-2.32.1-46.0.3.an8.x86_64 [songcy@anolis proj_repositories]$ yum --showduplicates list util-linux ... 已安装的软件包 util-linux.x86_64 2.32.1-46.0.3.an8 @BaseOS 可安装的软件包 util-linux.x86_64 2.32.1-43.0.1.an8 BaseOS util-linux.x86_64 2.32.1-44.0.1.an8.1 BaseOS util-linux.x86_64 2.32.1-45.0.1.an8.1 BaseOS util-linux.x86_64 2.32.1-46.0.1.an8 BaseOS util-linux.x86_64 2.32.1-46.0.3.an8 BaseOS [songcy@anolis proj_repositories]$ Changelog * Thu Feb 20 2025 Weisson <Weisson@linux.alibaba.com> 2.23.1-46.0.4 - bugfix: anbz 18732. - from upstream: https://github.com/util-linux/util-linux/pull/1294. 2. 其次 我考虑拉取 工具的最新代码 编译 RPM, 并替换到我们产品的根文件系统, 包含修复提交的 util-linux 源码, 我在哪能够获取, 地址能发一下不? 期待你的回复.
https://gitee.com/src-anolis-os/util-linux/tree/a8/(In reply to songcy2025 from comment #12) > (In reply to Weisson from comment #11) > > 构建完成,待发布 http://build.openanolis.cn/buildinfo?buildID=38895 > > Dear Weisson, > > 我正在关注 如何应用当前问题的解决方案 到我们的项目上. > > 1. 关于应用你的修复方案, 首先我能想到的是 直接 install 修复问题后的 rpm 包, > 我没有看到 "2.23.1-46.0.4" 版本的发布, 我在哪里可以找到这个版本? > > [songcy@anolis proj_repositories]$ rpm -qf $(which hwclock) > util-linux-2.32.1-46.0.3.an8.x86_64 > [songcy@anolis proj_repositories]$ yum --showduplicates list util-linux > ... > 已安装的软件包 > util-linux.x86_64 2.32.1-46.0.3.an8 @BaseOS > 可安装的软件包 > util-linux.x86_64 2.32.1-43.0.1.an8 BaseOS > util-linux.x86_64 2.32.1-44.0.1.an8.1 BaseOS > util-linux.x86_64 2.32.1-45.0.1.an8.1 BaseOS > util-linux.x86_64 2.32.1-46.0.1.an8 BaseOS > util-linux.x86_64 2.32.1-46.0.3.an8 BaseOS > [songcy@anolis proj_repositories]$ > > Changelog * Thu Feb 20 2025 Weisson <Weisson@linux.alibaba.com> 2.23.1-46.0.4 > - bugfix: anbz 18732. > - from upstream: https://github.com/util-linux/util-linux/pull/1294. > > 2. 其次 我考虑拉取 工具的最新代码 编译 RPM, 并替换到我们产品的根文件系统, > 包含修复提交的 util-linux 源码, 我在哪能够获取, 地址能发一下不? > > 期待你的回复. 项目地址在这里: https://gitee.com/src-anolis-os/util-linux/tree/a8/
(In reply to Weisson from comment #13) 收到, 谢谢 Weisson