This is an automated email from the ASF dual-hosted git repository.

acassis pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/nuttx-apps.git

commit 6e79ea2d85eca55763d533e3f1fd26d36feb0234
Author: Junbo Zheng <[email protected]>
AuthorDate: Mon Sep 14 14:55:45 2026 +0800

    monkey: block SIGTERM and consume it in sigtimedwait() for a clean exit
    
    Block SIGTERM at startup and add it to the sigtimedwait() set in
    monkey_wait(): a blocked signal is never swallowed by the handler, it
    either wakes the in-progress wait or stays pending on the task until
    the next sigtimedwait() returns it immediately, so the exit through
    the regular monkey_delete() cleanup path is deterministic. Because
    the kernel keeps the signal mask and pending queue per task, sibling
    monkey instances (e.g. multiple instances started for different
    input devices) each stop independently, and no shared state is
    involved.
    
    Also add a signal_handler() that logs the received signal and
    register it for SIGTSTP/SIGCONT/SIGTERM, so these signals never fall
    back to their default actions and stay consumable by sigtimedwait()
    / sigwaitinfo().
    
    Before:
    kill -15 <pid> terminates the task via the default SIGTERM action
    with no cleanup: no "monkey_delete: OK" is ever printed.
    
    After:
    kill -15 <pid> exits within one loop iteration (<= one event period,
    100-500ms by default) via monkey_delete(), independently for each
    running instance, and restarting monkey works.
    
    Testing:
    
    Built and verified on the NuttX simulator (host: Ubuntu 22.04):
    
      cmake -B build -DBOARD_CONFIG=sim:nsh -GNinja
      # enable in build/.config:
      #   CONFIG_INPUT=y
      #   CONFIG_GRAPHICS_INPUT_MONKEY=y
      #   CONFIG_NSH_MAXARGUMENTS=16
      ninja -C build olddefconfig && ninja -C build
      ./build/nuttx
    
    Run in the nsh prompt (uinput injection mode):
    
      nsh> monkey -t 0x11 -p 100-300 -s 454x454 &   (uinput touch)
      nsh> monkey -t 0x12 -p 100-300 -s 454x454 -b 0 &  (uinput button)
      nsh> ps
      nsh> kill -15 <pid>
    
    ps with both instances running (each monkey task shows "Waiting
    Signal" with SIGMASK 0x8000, i.e. SIGTERM blocked while sitting in
    sigtimedwait):
    
      TID   PID  PPID PRI POLICY   TYPE    NPX STATE    EVENT     SIGMASK       
     STACK COMMAND
        0     0     0   0 FIFO     Kthread   - Ready              
0000000000000000 0069584 Idle_Task
        1     0     0 224 FIFO     Kthread   - Waiting  Semaphore 
0000000000000000 0067456 sim_loop_wq 0x71204b2003f0 0x71204b200478
        2     0     0 224 FIFO     Kthread   - Waiting  Semaphore 
0000000000000000 0067464 hpwork 0x40188860 0x401888e8
        4     4     0 100 FIFO     Task      - Waiting  Semaphore 
0000000000000000 0067496 init_main
        9     9     4 100 FIFO     Task      - Running            
0000000000000000 0067504 sh
       10    10     9 110 FIFO     Task      - Waiting  Signal    
0000000000008000 0069472 monkey -t 0x11 -p 100-300 -s 454x454
       11    11     9 110 FIFO     Task      - Waiting  Signal    
0000000000008000 0069448 monkey -t 0x12 -p 100-300 -s 454x454 -b 0
    
    After "kill -15 10" (touch instance exits, button instance
    unaffected):
    
      nsh> kill -15 10
      [monkey] monkey_wait: Recv sig: SIGTERM
      [monkey] monkey_delete: OK
      nsh> ps
      TID   PID  PPID PRI POLICY   TYPE    NPX STATE    EVENT     SIGMASK       
     STACK COMMAND
        0     0     0   0 FIFO     Kthread   - Ready              
0000000000000000 0069584 Idle_Task
        1     0     0 224 FIFO     Kthread   - Waiting  Semaphore 
0000000000000000 0067456 sim_loop_wq 0x71204b2003f0 0x71204b200478
        2     0     0 224 FIFO     Kthread   - Waiting  Semaphore 
0000000000000000 0067464 hpwork 0x40188860 0x401888e8
        4     4     0 100 FIFO     Task      - Waiting  Semaphore 
0000000000000000 0067496 init_main
        9     9     4 100 FIFO     Task      - Running            
0000000000000000 0067504 sh
       11    11     9 110 FIFO     Task      - Waiting  Signal    
0000000000008000 0069448 monkey -t 0x12 -p 100-300 -s 454x454 -b 0
    
    After "kill -15 11" (second instance exits the same way, no monkey
    task left):
    
      nsh> kill -15 11
      [monkey] monkey_wait: Recv sig: SIGTERM
      [monkey] monkey_delete: OK
      nsh> ps
      TID   PID  PPID PRI POLICY   TYPE    NPX STATE    EVENT     SIGMASK       
     STACK COMMAND
        0     0     0   0 FIFO     Kthread   - Ready              
0000000000000000 0069584 Idle_Task
        1     0     0 224 FIFO     Kthread   - Waiting  Semaphore 
0000000000000000 0067456 sim_loop_wq 0x71204b2003f0 0x71204b200478
        2     0     0 224 FIFO     Kthread   - Waiting  Semaphore 
0000000000000000 0067464 hpwork 0x40188860 0x401888e8
        4     4     0 100 FIFO     Task      - Waiting  Semaphore 
0000000000000000 0067496 init_main
        9     9     4 100 FIFO     Task      - Running            
0000000000000000 0067504 sh
    
    A new instance started after both kills (PID 12) runs normally and
    is again stopped cleanly by kill -15.
    
    Note: on the simulator the uinput devices register as /dev/utouch
    and /dev/ubutton, while monkey opens /dev/input0 and /dev/buttons;
    the run above used a local (uncommitted) path patch to work around
    this. On a board where the device paths match, no patch is needed.
    
    Assisted-by: Claude Code (glm-5.3) <[email protected]>
    Signed-off-by: Junbo Zheng <[email protected]>
---
 graphics/input/monkey/monkey_main.c | 33 +++++++++++++++++++++++++++++++++
 1 file changed, 33 insertions(+)

diff --git a/graphics/input/monkey/monkey_main.c 
b/graphics/input/monkey/monkey_main.c
index 43b0561c0..f495bea59 100644
--- a/graphics/input/monkey/monkey_main.c
+++ b/graphics/input/monkey/monkey_main.c
@@ -516,6 +516,7 @@ static enum monkey_wait_res_e monkey_wait(uint32_t ms)
 
   sigemptyset(&set);
   sigaddset(&set, SIGTSTP);
+  sigaddset(&set, SIGTERM);
 
   ret = sigtimedwait(&set, NULL, &timeout);
 
@@ -539,10 +540,24 @@ static enum monkey_wait_res_e monkey_wait(uint32_t ms)
     {
       res = MONKEY_WAIT_RES_PAUSE;
     }
+  else if (ret == SIGTERM)
+    {
+      MONKEY_LOG_WARN("Recv sig: SIGTERM");
+      res = MONKEY_WAIT_RES_STOP;
+    }
 
   return res;
 }
 
+/****************************************************************************
+ * Name: signal_handler
+ ****************************************************************************/
+
+static void signal_handler(int sig)
+{
+  MONKEY_LOG_WARN("Recv sig: %d", sig);
+}
+
 /****************************************************************************
  * Public Functions
  ****************************************************************************/
@@ -565,8 +580,26 @@ int main(int argc, FAR char *argv[])
   struct monkey_param_s param;
   FAR struct monkey_s *monkey;
   uint32_t start_tick;
+  sigset_t mask;
+
   parse_commandline(argc, argv, &param);
 
+  /* Block SIGTERM and let sigtimedwait() consume it: the signal mask
+   * and pending queue are per task, so sibling monkey instances stop
+   * independently, and a signal arriving outside the wait window stays
+   * pending instead of being swallowed by the handler.
+   */
+
+  sigemptyset(&mask);
+  sigaddset(&mask, SIGTERM);
+  sigprocmask(SIG_BLOCK, &mask, NULL);
+
+  /* Add signal handler to avoid system default handler */
+
+  signal(SIGTSTP, &signal_handler);
+  signal(SIGCONT, &signal_handler);
+  signal(SIGTERM, &signal_handler);
+
   monkey = monkey_init(&param);
 
   if (!monkey)

Reply via email to