ankohuu opened a new pull request, #18672:
URL: https://github.com/apache/nuttx/pull/18672
## Summary
A signal can arrive before `sem_wait` transitions the task to
`TSTATE_WAIT_SEM`. In that window, the wait cannot yet be
aborted by `sem_wait_irq()`. If `sem_wait` then blocks without
re-checking unmasked pending signals, it can sleep
indefinitely and miss the interrupt.
Check for unmasked pending signals in wait critical section
and return `-EINTR` if one is already pending.
Overall, the expected semantics are that `sem_wait()` should
not block if there is already an unmasked pending signal that
should interrupt the wait. This patch enforces that behavior
by checking for unmasked pending signals before the
task can sleep.
## Impact
May bugfix not behavior change
## Testing
I confirm that the change was built and runtime-tested on a local setup.
- Build host: Linux x86_64
- Toolchain: local NuttX RISC-V GCC toolchain
- Target: qemu-rv:rv-virt
- Build mode: CONFIG_BUILD_PROTECTED=y
- SMP: CONFIG_SMP=y, CONFIG_SMP_NCPUS=2
### Code
```
Add delay in sem_wait_slow before entring critical secion
+ if (strncmp(get_task_name(rtcb), "semhook_waiter",
+ CONFIG_TASK_NAME_SIZE) == 0 &&
+ !g_semhook_waited)
+ {
+ g_semhook_waited = true;
+ up_mdelay(500);
+ }
The apps-side test is a targeted reproducer rather than a general
regression
test. It creates a dedicated waiter thread, widens the pre-WAIT_SEM
window
through a test hook, sends one signal, and then waits for the waiter
thread
to exit.
+void signest_semhook_test(void)
+{
..
+ ret = pthread_create(&waiter, NULL, waiter_main, NULL);
+ ret = sem_wait(&g_semhook_ready);
+ pthread_join(waiter, NULL);
+static FAR void *waiter_main(FAR void *arg)
+{
..
+ sem_post(&g_semhook_ready);
+ ret = sem_wait(&g_semhook_sem);
```
###Logs before this change
```
NuttShell (NSH) NuttX-12.13.0
nsh> ostest
stdio_test: write fd=1
stdio_test: Standard I/O Check: printf
stdio_test: write fd=2
stdio_test: Standard I/O Check: fprintf to stderr
ostest_main: putenv(Variable1=BadValue3)
ostest_main: setenv(Variable1, GoodValue1, TRUE)
ostest_main: setenv(Variable2, BadValue1, FALSE)
ostest_main: setenv(Variable2, GoodValue2, TRUE)
ostest_main: setenv(Variable3, GoodValue3, FALSE)
ostest_main: setenv(Variable3, BadValue2, FALSE)
show_variable: Variable=Variable1 has value=GoodValue1
show_variable: Variable=Variable2 has value=GoodValue2
show_variable: Variable=Variable3 has value=GoodValue3
ostest_main: Started user_main at PID=6
user_main: semhook test
hang..
```
###Logs after this change
```
user_main: semhook test
signest_semhook_test: done
user_main: Exiting
ostest_main: Exiting with status 0
nsh>
```
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]