Plain C:定时器ID无法传入信号处理函数及siginfo.h异常问题
问题分析与临时解决及上报指引
问题现象
在信号处理函数中尝试通过siginfo_t的si_timerid获取定时器ID时,即便timer_create()执行成功,运行时si_timerid的值始终为0。进一步排查系统头文件后发现:
man signals手册中明确标注siginfo_t结构包含si_timerid字段(用于存储POSIX.1b定时器ID)- 实际头文件(由
signal.h引入的siginfo.h)并未直接定义该字段,而是通过宏定义实现:#define si_timerid _sifields._timer.si_tid - 测试代码显示,直接访问
s_info->_sifields._timer.si_sigval.sival_int能获取到正确的定时器ID,但si_timerid无法正常工作;同时直接访问s_info->_sifields._timer.si_overrun会触发编译错误——因为si_overrun同样是宏定义:
宏展开后会变成#define si_overrun _sifields._timer.si_overruns_info->_sifields._timer._sifields._timer.si_overrun,属于重复替换导致的语法错误。
问题根源
这是系统头文件的宏定义实现缺陷:
si_timerid的宏指向了错误的底层字段(si_tid而非实际存储定时器ID的si_sigval.sival_int)si_overrun的宏定义存在符号冲突,手动访问底层结构字段会触发重复展开
临时解决方案
在官方修复前,可绕过宏定义直接访问正确的底层字段:
// 获取正确的定时器ID timer_t timer_id = s_info->_sifields._timer.si_sigval.sival_int;
对于si_overrun,直接使用宏定义访问即可避免错误:
// 用宏定义访问si_overrun,避免手动展开引发的重复替换 int overrun = s_info->si_overrun;
问题上报途径
若确认是系统头文件bug,可根据使用的操作系统选择对应渠道:
- Linux系统:通过Linux内核邮件列表(如
linux-api@vger.kernel.org或linux-man@vger.kernel.org)提交问题,附上测试代码、头文件版本、系统环境信息;也可在发行版自带的bug跟踪系统(如Debian BTS、Red Hat Bugzilla)提交报告。 - BSD类系统:提交至对应BSD的开发者邮件列表或官方bug跟踪平台(如FreeBSD Bugzilla)。
- 其他UNIX-like系统:参考官方文档的bug提交指引,提供清晰的复现步骤、环境信息和问题分析。
内容的提问来源于stack exchange,提问作者Hoks
相关产品推荐
相关产品推荐

