<!--- 请清晰详细地描述你遇到的问题,描述问题时请给出芯片/BSP/工具链,RT-Thread版本,复现步骤及现象或者有条理地描述你的问题。在问题得到解决后,请及时关闭issue。欢迎到论坛提问:https://club.rt-thread.org/ --> <!--- Please describe your problem clearly and in detail. When describing the problem, please use numbers or bullet points to describe your problem coherently. After the problem is resolved, please close the issue in time. Welcome to the forum to ask questions: https://club.rt-thread.io/ --> # 问题 mtuex 在 suspend 之前没有重置 thread->error 导致被信号中断后没有正确得到反馈。 https://github.com/RT-Thread/rt-thread/blob/a6fcb4f8a13709e836b9133a08d573fc0dfd398a/src/ipc.c#L1246 参考 sem 的方式如下: https://github.com/RT-Thread/rt-thread/blob/a6fcb4f8a13709e836b9133a08d573fc0dfd398a/src/ipc.c#L548-L554
Activity
polarvid commentedon Aug 3, 2023
另外,这种判断方式感觉不是很好。会导致线程状态误判,参考 #6768 。
也许改成 rt_wake_up 中去设置错误码会好些。
Yunlk commentedon Oct 24, 2026
在 QEMU 上按 issue 描述的场景测了一遍,当前 master 上这个现象已经不复现:被信号打断后
rt_mutex_take_interruptible()确实返回了-RT_EINTR。先把过程和数据放上来,请确认一下是不是我理解错了你指的那条路径。复现环境
bsp/qemu-vexpress-a9,QEMU 11.0.0,arm-none-eabi-gcc 15.2.1,master1c801efaRT_USING_SIGNALS,要先打开才能测信号(CONFIG_RT_USING_SIGNALS=y)场景
holder(priority 15)先rt_mutex_take()拿到互斥量,然后睡 3 秒waiter(priority 16)安装SIGUSR1处理函数并 unmask,随后调用rt_mutex_take_interruptible(mtx, RT_WAITING_FOREVER)阻塞rt_thread_kill(waiter, SIGUSR1)实测输出
-4就是-RT_EINTR,且信号处理函数被调用了一次,waiter 没有卡死。为什么已经正确了
当前 master 用的不是你说的"suspend 前预置
RT_EINTR",而是在恢复之后兜底转换——src/ipc.c的_rt_mutex_take()里:也就是说:被信号唤醒、但没有真正拿到互斥量时,
thread->error仍是RT_EOK,于是:1476把它转成-RT_EINTR返回给调用者。行为上等价于你建议的效果,只是实现位置不同。对比一下现在三类 IPC 的处理方式确实不一致:
thread->error = -RT_EINTR(或RT_EINTR,sem 那处是正值)RT_EOK,恢复后按owner != thread && error == EOK推断"意外唤醒"两点想确认
rt_mutex_take_interruptible()还是普通的rt_mutex_take()? 我只测了前者——普通版用RT_UNINTERRUPTIBLE挂起,信号本来就不该打断它,所以那种情况不存在"返回什么错误"的问题。如果你当时测的是普通版,那可能现象不同,请说明。polarvid提到的状态误判(ps命令查询线程状态,由于rt_thread_sleep中临时改变状态会导致ps出的状态与实际状态不一致,影响判断 #6768)是否还在? 现在这个兜底是"用error == RT_EOK反推被信号打断",本质是个启发式判断。如果某条路径上线程被唤醒、error恰好是EOK、又确实没拿到锁,就会被记成-EINTR;反之若别的原因把error置成了非EOK,返回值也会跟着变。这个隐患没有因为我上面的测试被排除——测试只证明了"信号打断这一条路径"结果是正确的。建议
ipc.c:1476-1479的兜底逻辑)。polarvid说的状态误判仍要处理,那是一个独立问题,范围比"补一行置 EINTR"要大,建议另开一条,明确"谁在什么时机设置错误码"的约定。复现代码是临时 app,没有提交。需要的话我可以整理成
src/utest/下的用例——不过它依赖RT_USING_SIGNALS,进 CI 得确认那几个 BSP 的配置支持。