[kernel/signal] fix: respect thread suspend mode during signal delivery - #11723
[kernel/signal] fix: respect thread suspend mode during signal delivery#11723liulangrenaaa wants to merge 1 commit into
Conversation
|
👋 感谢您对 RT-Thread 的贡献!Thank you for your contribution to RT-Thread! 为确保代码符合 RT-Thread 的编码规范,请在你的仓库中执行以下步骤运行代码格式化工作流(如果格式化CI运行失败)。 🛠 操作步骤 | Steps
完成后,提交将自动更新至 如有问题欢迎联系我们,再次感谢您的贡献!💐 |
📌 Code Review Assignment🏷️ Tag: kernelReviewers: @GorrayLi @ReviewSun @hamburger-os @lianux-mm @wdfk-prog @xu18838022837 Changed Files (Click to expand)
📊 Current Review Status (Last Updated: 2026-08-20 17:31 CST)
📝 Review Instructions
|
|
Native signal delivery resumed every suspended thread, including RT_UNINTERRUPTIBLE IPC waiters. This could remove a waiter from a semaphore, mutex, event, mailbox, or message queue wait list without granting the corresponding resource, causing -RT_EINTR or inconsistent higher-level state. Inspect pending signals and suspend state under scheduler ownership. Wake interruptible waiters for common signals, and wake killable waiters only for SIGKILL and SIGSTOP according to RT-Thread suspend semantics. Defer signals not allowed by the current wait mode. Release the signal lock before waking the target thread. Also make scheduler-side pending-signal preprocessing respect the suspend mode, preventing SMP suspend-to-schedule races. Keep rt_signal_wait() blocked for non-matching signals and preserve the remaining timeout. Allow masked signals and NULL siginfo, handle suspend failures without starting a timer, and preserve the outer interrupted wait result when a signal handler invokes other kernel APIs. Add regression coverage for RT-Thread native signal semantics, including masked signals, non-matching signal waits, NULL siginfo, and RT_KILLABLE SIGSTOP handling. The parent implementation fails the regression test because uninterruptible and killable waits complete early after SIGUSR1, and signal_wait returns early for a non-matching signal. Validation: - UP QEMU: core.signal passed. - Dual-core SMP QEMU: core.signal passed. - scons -C bsp/qemu-vexpress-a9 -j$(nproc) passed. Signed-off-by: Hui Su <3164683437@qq.com>
e1b3b9c to
04e1d7d
Compare
拉取/合并请求描述:(PR description)
为什么提交这份PR (why to submit this PR)
当前 RT-Thread native signal delivery 会无条件唤醒所有处于 suspended 状态的线程,而不会考虑线程当前的 suspend mode。
这会破坏线程阻塞等待的语义。
例如,当线程通过
rt_sem_take()在不可中断等待 (RT_UNINTERRUPTIBLE) 中等待信号量时,如果此时收到普通信号:rt_sem_take()返回-RT_EINTR;类似问题不仅限于 semaphore,也可能影响其他依赖 thread suspend/wakeup 机制的同步原语,例如 mutex、event、mailbox 和 message queue。
根本原因是 signal delivery 路径没有遵守 RT-Thread thread suspend semantics,导致 signal wakeup 错误地抢占了其他 wakeup source(例如 IPC release 或 timeout)的 ownership。
你的解决方案是什么 (what is your solution)
在唤醒 suspended thread 之前,同时检查 pending signal 和完整 suspend state,并在 scheduler ownership 下决定该 signal 是否允许唤醒线程。
当前 signal wakeup 规则:
RT_THREAD_STAT_SIGNAL_WAIT:rt_signal_wait()的正常 signal wakeup 行为。RT_INTERRUPTIBLE:RT_KILLABLE:SIGKILL和SIGSTOP可以唤醒等待线程。RT_UNINTERRUPTIBLE:同时:
RT_EINTR;rt_thread_resume()/rt_thread_wakeup()前释放 signal lock;另外修复:
rt_signal_wait()收到 non-matching signal 时继续保持等待;rt_signal_wait()持有 pending signal 时错误设置 generic signal state;测试覆盖 (Regression tests)
新增回归测试覆盖 native signal delivery 与不同 suspend mode 的交互:
signal_waitRT_UNINTERRUPTIBLEsemaphore waitRT_INTERRUPTIBLEsemaphore waitRT_KILLABLEsemaphore waitSIGSTOPhandling according to RT-Thread native signal semantics父分支测试失败:
RT_UNINTERRUPTIBLEwait 在收到普通信号后提前返回;RT_KILLABLEwait 错误响应普通信号;rt_signal_wait()收到 non-matching signal 后提前结束等待。修复后验证通过:
UP QEMU:
core.signalpassedDual-core SMP QEMU:
core.signalpassedBuild:
scons -C bsp/qemu-vexpress-a9 -j$(nproc)passed请提供验证的bsp和config (provide the config and bsp)
BSP:
bsp/qemu-vexpress-a9.config:
Validation:
Parent revision with regression tests:
core.signalfailed due to incorrect early wakeup and non-matching signal handling.Fixed revision:
Build:
scons -C bsp/qemu-vexpress-a9 -j$(nproc)passedaction:
当前拉取/合并请求的状态 Intent for your PR
必须选择一项 Choose one (Mandatory):
代码质量 Code Quality:
我在这个拉取/合并请求中已经考虑了 As part of this pull request, I've considered the following:
#if 0代码,不包含已经被注释了的代码 All redundant code is removed and cleaned up