[Bug] [libc] timer_gettime 拆秒前将总纳秒截断为 uint32_t,剩余时间查询错误
I maintainer di solito rispondono entro 1 giorno
@Yunlk ci sta già lavorando.
Dal 24/10/2026.
Valutazione
- Difficoltà
- 2/5
- Tempo stimato
- 1-3 ore
- Idoneità per principianti
- 68/100
- Tipo di issue
- Bug
- Chiarezza
- Specificata chiaramente
- Stato di attività
- Attiva
- Stack tecnologico
- c
- Ambito
- backend, operating-systems
Direzione di ricerca
Leggi components/libc/compilers/common/ctime.c, in particolare timer_gettime() intorno alle righe segnalate 1337–1375, e segui la conversione dei tick rimanenti del contatore in nanosecondi. L’esempio aritmetico autonomo dimostra il troncamento; riproducilo, quindi verifica il risultato per un tempo rimanente di 10 secondi dopo la modifica. Mantieni i controlli per il wraparound del contatore e per l’intervallo della moltiplicazione intermedia, e conferma che la configurazione del timer POSIX abilita questo codice.
Scritto dal modello di indicizzazione a partire dal testo della issue.
Descrizione
RT-Thread Version
master, commit a59e72fb5c2f272761a2813fc9bd9fe18eb29d7d.
Affected area
libc / POSIX timers, components/libc/compilers/common/ctime.c, timer_gettime().
Hardware / Architecture / Toolchain
采用源码级算术隔离复现,不依赖特定开发板。该提交中的受影响实现由 RT_USING_POSIX_TIMER && RT_USING_CLOCK_TIME 启用。本报告尚未进行目标板复现。
问题描述 / Describe the bug
timer_gettime() 将总剩余纳秒存入 rt_uint32_t,之后才拆分秒和纳秒:
rt_uint32_t seconds, nanoseconds;
/* ... */
nanoseconds = ((remain_cnt - rt_clock_time_get_counter())
* rt_clock_time_get_res_scaled()) / RT_CLOCK_TIME_RESMUL;
seconds = nanoseconds / NANOSECOND_PER_SECOND;
nanoseconds = nanoseconds % NANOSECOND_PER_SECOND;
即使计数器表达式正确算出 10 秒,即 10,000,000,000 ns,赋给 32 位无符号变量时也会变成 1,410,065,408 ns。查询结果因此是 {tv_sec=1, tv_nsec=410065408},而不是 {10, 0}。
可运行的隔离复现 / Standalone arithmetic reproduction
下面明确模拟计数器换算已经正确得到总纳秒的情况,不调用宿主 libc 的 timer_gettime():
#include <assert.h>
#include <stdint.h>
#include <stdio.h>
int main(void)
{
uint64_t converted_ns = UINT64_C(10000000000);
uint32_t seconds, nanoseconds;
nanoseconds = converted_ns;
seconds = nanoseconds / 1000000000;
nanoseconds %= 1000000000;
printf("%u.%09u\n", (unsigned)seconds, (unsigned)nanoseconds);
assert(seconds == 1 && nanoseconds == 410065408);
return 0;
}
输出:1.410065408;预期剩余时间为 10.000000000。
此前还在本地旧版同一函数的隔离计数器桩中复现过该结果;最新上游同样保留上述窄化顺序。完整目标端验证仍待进行。
Scope / Suggested direction
- 问题从总纳秒超过
UINT32_MAX(约 4.295 秒)起出现,不是几十年后的时间范围问题。 - 这是剩余时间查询结果错误,不表示定时器一定提前或延后触发。
- 后面的
(rt_int32_t)seconds不是这里的根因,数据在拆秒之前已经丢失。 - 建议总纳秒使用足够宽的类型,再拆分秒和纳秒;或在安全的单位下先拆秒、再换算余数。还应保留对计数器回绕及中间乘法范围的检查。
引入提交和版本 / Regression history
- 引入提交:0eb75ced70,2023-07-17,
[time]时钟框架重构 (#7794);首个包含该提交的正式 release 为 v5.0.2。 - 此前使用 64 位
remaining保存总纳秒,再分别赋值给秒和纳秒字段;该提交改为将总纳秒直接赋给 32 位nanoseconds,然后再拆秒。 rt_uint32_t seconds, nanoseconds的声明本身在更早实现中已经存在,但当时用于保存拆分后的字段,并非这次回归的来源。- 后续 743b614875 的时间子系统重构更换了计数接口名称,但保留了该窄化顺序。
其他实现参考 / Comparison
Linux 使用 64 位 ktime_t 转 timespec64;Zephyr 则先从剩余毫秒中拆秒,再将余数转换为纳秒。两种方式均避免这里的总纳秒 32 位中转。这不是对这些 OS 所有计时边界行为的保证。
- Lingua principale
- C
- Stelle
- 12.3k
- Fork
- 5.5k
- Merge medio
- 4g 9h
- PR unite (30g)
- 37
Preparare l'ambiente
Avvia il container di sviluppo del progetto nel browser, con il tuo account GitHub.
- Nessun Dockerfile né file Docker Compose
- Ha un modello di pull request
- Leggi la guida per i contributori
Come iniziare
- Leggi tutta la issue e poi la guida ai contributi del progetto.
- Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
- Fai un fork del repository e lavora su un branch.
- Apri una pull request che faccia riferimento al numero della issue.
Altre issue di RT-Thread/rt-thread
-
bug
Difficoltà 2/5 1-3 ore Idoneità per principianti 67/100
RT-Thread/rt-thread#11951 · 1 commento ·
I maintainer di solito rispondono entro 1 giorno
-
bug
Difficoltà 2/5 1-3 ore Idoneità per principianti 72/100
RT-Thread/rt-thread#11949 · 1 commento ·
I maintainer di solito rispondono entro 1 giorno
-
[Bug] RT-Thread AB32 ADC uses an unchecked channel as a register indexForse già presa @usualtreee l’ha presa 3 giorni fa. Apertabug Component component: drivers
Difficoltà 2/5 1-3 ore Idoneità per principianti 72/100
RT-Thread/rt-thread#11948 · 1 commento ·
I maintainer di solito rispondono entro 1 giorno
-
[Bug] dfs_v2 tmpfs: ftruncate(fd, 0) frees the file buffer but reports success — use-after-free read/write and double free from a legal POSIX callForse già presa @remukisama l’ha presa 14 giorni fa. Apertain progress
Difficoltà 2/5 1-3 ore Idoneità per principianti 78/100
RT-Thread/rt-thread#11902 · 4 commenti · 1 assegnatario ·
I maintainer di solito rispondono entro 1 giorno
-
[bsp][stm32][bluepill] README「快速上手」缺少重新生成 MDK 工程这一步,按文档操作无法编译通过Forse di nuovo libera @moment-NEW l’ha presa 31 giorni fa e non c’è nessuna pull request aperta. Apertain progress
Difficoltà 2/5 1-3 ore Idoneità per principianti 75/100
RT-Thread/rt-thread#11818 · 4 commenti · 1 assegnatario ·
I maintainer di solito rispondono entro 1 giorno
Tutte le issue di RT-Thread/rt-thread
Issue simili
-
Bug
Difficoltà 2/5 1-3 ore Idoneità per principianti 66/100
I maintainer di solito rispondono entro 1 giorno
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 70/100
meshcore-dev/MeshCore#3760 · 1 commento ·
I maintainer di solito rispondono entro 1 giorno
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 68/100
ly05010419/MacNativeGames#1697 ·
I maintainer di solito rispondono entro 1 giorno
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 70/100
colbymchenry/codegraph#3228 ·
I maintainer di solito rispondono entro 1 giorno
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 65/100
FujiNetWIFI/fujinet-config#372 ·
I maintainer di solito rispondono entro 1 giorno