Junbo-Zheng opened a new pull request, #20728:
URL: https://github.com/apache/nuttx/pull/20728

   
   ## Summary
   
   The sleep family (nanosleep, clock_nanosleep, sleep, usleep) blocks
   in nxsig_clockwait(), which never installs a sigunbinfo buffer. So
   when an unblocked caught signal awakens the sleeper, the wake reason
   is nowhere to be found and the function unconditionally returns OK:
   the caller sees a completed sleep (ret 0) instead of -1/EINTR, and
   EINTR-based retry loops never fire.
   
   Fix: nxsig_clockwait() now installs its own stack sigunbinfo buffer
   when the caller did not provide one (only nxsig_timedwait() does),
   and after waking reports -EINTR for a real signal (signo 1..63) and
   -ECANCELED on cancellation; a watchdog timeout still returns OK. The
   sigtimedwait() path is untouched.
   
   The second commit fixes a pre-existing nxstyle error (misaligned
   wd_start_abstick() continuation lines) that checkpatch flags on any
   commit touching this file.
   
   ## Impact
   
   - **Users**: nanosleep()/clock_nanosleep()/sleep()/usleep() now
     correctly return -1/EINTR when interrupted by a caught, unblocked
     signal. This restores the POSIX behavior documented for these
     functions. Code that (incorrectly) relied on the interrupted-sleep
     return value being 0 will see the fix.
   - **Build**: None.
   - **Hardware**: None -- scheduler-only change, verified on sim.
   - **Documentation**: None -- the function headers already document
     EINTR; the code now matches them.
   - **Security & Compatibility**: None.
   
   ## Testing
   
   Built and verified on the NuttX simulator (host: Ubuntu 22.04), with
   the apps repository checked out alongside (test applied temporarily
   to apps/examples/hello, not part of this PR):
   
       cmake -B build -DBOARD_CONFIG=sim:nsh
       cmake --build build -j$(nproc)
       ./build/nuttx
       nsh> hello
   
   Complete test used, as a diff against the pristine
   apps/examples/hello/hello_main.c:
   
   ```diff
   diff --git a/examples/hello/hello_main.c b/examples/hello/hello_main.c
   --- a/examples/hello/hello_main.c
   +++ b/examples/hello/hello_main.c
   @@ -26,17 +26,91 @@
    
    #include <nuttx/config.h>
    #include <stdio.h>
   +#include <signal.h>
   +#include <time.h>
   +#include <unistd.h>
   +#include <errno.h>
   +#include <sched.h>
    
    
/****************************************************************************
   - * Public Functions
   + * Private Data
     
****************************************************************************/
    
   +static pid_t g_target;
   +
   
+/****************************************************************************
   + * Private Functions
   + 
****************************************************************************/
   +
   +static void usr1_handler(int signo)
   +{
   +  printf("hello: SIGUSR1 handler fired (signo=%d)\n", signo);
   +}
   +
   +static int killer_main(int argc, char *argv[])
   +{
   +  usleep(500 * 1000);
   +  printf("hello: killer sending SIGUSR1 to pid=%d\n", g_target);
   +  kill(g_target, SIGUSR1);
   +  return 0;
   +}
   +
   
+/****************************************************************************
   + * Public Functions
   + 
****************************************************************************/
   +
   
+/****************************************************************************
   + * hello_main
   + 
****************************************************************************/
   +
    int main(int argc, FAR char *argv[])
    {
   -  printf("Hello, World!!\n");
   -  return 0;
   +  struct sigaction act;
   +  struct timespec req;
   +  struct timespec rem;
   +  struct timespec tmo;
   +  sigset_t set;
   +  siginfo_t info;
   +  int ret;
   +
   +  /* Case 1: nanosleep interrupted by a caught unmasked signal */
   +
   +  act.sa_handler = usr1_handler;
   +  act.sa_flags   = 0;
   +  sigemptyset(&act.sa_mask);
   +  sigaction(SIGUSR1, &act, NULL);
   +
   +  req.tv_sec  = 3;
   +  req.tv_nsec = 0;
   +  rem.tv_sec  = -1;
   +  rem.tv_nsec = -1;
   +
   +  printf("hello: case1 nanosleep(3s), killed after 0.5s\n");
   +  g_target = getpid();
   +  task_create("killer", 100, 2048, killer_main, NULL);
   +  ret = nanosleep(&req, &rem);
   +  printf("hello: case1 nanosleep ret=%d errno=%d (EINTR=%d), "
   +         "rem=%ld.%09ld\n",
   +         ret, errno, EINTR, (long)rem.tv_sec, (long)rem.tv_nsec);
   +  printf("hello: case1 %s\n",
   +         (ret == -1 && errno == EINTR) ? "PASS (EINTR)" : "FAIL");
   +
   +  /* Case 2: normal nanosleep completion (no signal) */
   +
   +  req.tv_sec  = 0;
   +  req.tv_nsec = 200 * 1000 * 1000;
   +  ret = nanosleep(&req, &rem);
   +  printf("hello: case2 plain nanosleep(0.2s) ret=%d errno=%d "
   +         "(expect 0/0)\n", ret, errno);
   +  printf("hello: case2 %s\n", (ret == 0) ? "PASS" : "FAIL");
   +
   +  /* Case 3: sigtimedwait timeout must still work (EAGAIN, no EINTR) */
   +
   +  sigemptyset(&set);
   +  sigaddset(&set, SIGUSR2);
   +  tmo.tv_sec  = 0;
   +  tmo.tv_nsec = 200 * 1000 * 1000;
   +  ret = sigtimedwait(&set, &info, &tmo);
   +  printf("hello: case3 sigtimedwait(0.2s) ret=%d errno=%d "
   +         "(EAGAIN=%d)\n", ret, errno, EAGAIN);
   +  printf("hello: case3 %s\n",
   +         (ret == -1 && errno == EAGAIN) ? "PASS (EAGAIN)" : "FAIL");
   +
   +  return 0;
    }
   ```
   
   Before:
   
       nsh> hello
       hello: case1 nanosleep(3s), killed after 0.5s
       hello: killer sending SIGUSR1 to pid=10
       hello: SIGUSR1 handler fired (signo=10)
       hello: case1 nanosleep ret=0 errno=0 (EINTR=4), rem=2.500000000
       hello: case1 FAIL
       hello: case2 plain nanosleep(0.2s) ret=0 errno=0 (expect 0/0)
       hello: case2 PASS
       hello: case3 sigtimedwait(0.2s) ret=-1 errno=11 (EAGAIN=11)
       hello: case3 PASS (EAGAIN)
   
   After:
   
       nsh> hello
       hello: case1 nanosleep(3s), killed after 0.5s
       hello: killer sending SIGUSR1 to pid=10
       hello: SIGUSR1 handler fired (signo=10)
       hello: case1 nanosleep ret=-1 errno=4 (EINTR=4), rem=2.500000000
       hello: case1 PASS (EINTR)
       hello: case2 plain nanosleep(0.2s) ret=0 errno=4 (expect 0/0)
       hello: case2 PASS
       hello: case3 sigtimedwait(0.2s) ret=-1 errno=11 (EAGAIN=11)
       hello: case3 PASS (EAGAIN)
   
   - case1 shows the fix: an interrupted sleep now returns -1/EINTR with
   the remaining time in rem. 
   - case2 verifies an uninterrupted sleep
   still returns 0 (errno left untouched on success). 
   - case3 verifies the sigtimedwait() path still times out with EAGAIN, i.e. 
   the timedwait sigunbinfo handling is unaffected.
   
   Signed-off-by: Junbo Zheng <[email protected]>
   


-- 
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]

Reply via email to