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

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


The following commit(s) were added to refs/heads/master by this push:
     new 09a59b9c8 testing/ostest: Add pthread_sigqueue test
09a59b9c8 is described below

commit 09a59b9c8bee163ec2f75cd55789233f11bce074
Author: Swatantra Yadav <[email protected]>
AuthorDate: Sun Nov 1 16:53:54 2026 +0530

    testing/ostest: Add pthread_sigqueue test
    
    Add automated unit test for pthread_sigqueue() in ostest to verify
    signal and payload delivery to a target pthread. Tests error handling
    for invalid signal numbers and non-existent thread IDs, as well as
    successful signal dispatch and reception with SA_SIGINFO and SI_QUEUE.
    
    Now that pthread_sigqueue() is implemented as a system call
    (apache/nuttx#21070), the test runs across flat, protected, and
    kernel builds.
    
    Configurable via CONFIG_TESTING_OSTEST_PTHREAD_SIGQUEUE, enabled by
    default for non-small builds (!DEFAULT_SMALL) and gated by
    ENABLE_ALL_SIGNALS and !DISABLE_PTHREAD. Progress output and error
    messages are streamlined to minimize the flash footprint.
    
    Signed-off-by: Swatantra Yadav <[email protected]>
---
 testing/ostest/CMakeLists.txt     |   4 +
 testing/ostest/Kconfig            |   8 ++
 testing/ostest/Makefile           |   3 +
 testing/ostest/ostest.h           |   6 +
 testing/ostest/ostest_main.c      |   8 ++
 testing/ostest/pthread_sigqueue.c | 277 ++++++++++++++++++++++++++++++++++++++
 6 files changed, 306 insertions(+)

diff --git a/testing/ostest/CMakeLists.txt b/testing/ostest/CMakeLists.txt
index fdcc9e187..0580c86a0 100644
--- a/testing/ostest/CMakeLists.txt
+++ b/testing/ostest/CMakeLists.txt
@@ -93,6 +93,10 @@ if(CONFIG_TESTING_OSTEST)
     list(APPEND SRCS timedwait.c pthread_rwlock.c pthread_rwlock_cancel.c
          schedlock.c)
 
+    if(CONFIG_TESTING_OSTEST_PTHREAD_SIGQUEUE)
+      list(APPEND SRCS pthread_sigqueue.c)
+    endif()
+
     if(CONFIG_SCHED_WAITPID)
       list(APPEND SRCS pthread_exit.c)
     endif()
diff --git a/testing/ostest/Kconfig b/testing/ostest/Kconfig
index d9c9af48a..ee0c32583 100644
--- a/testing/ostest/Kconfig
+++ b/testing/ostest/Kconfig
@@ -153,6 +153,14 @@ config TESTING_OSTEST_MULTIUSER
                CONFIG_LIBC_PASSWD_FILEPATH (default /tmp/ostest_passwd when 
this
                option is enabled).
 
+config TESTING_OSTEST_PTHREAD_SIGQUEUE
+       bool "pthread_sigqueue test"
+       default !DEFAULT_SMALL
+       depends on ENABLE_ALL_SIGNALS && !DISABLE_PTHREAD
+       ---help---
+               Enable automated unit test for pthread_sigqueue() in ostest to
+               verify signal and payload delivery to a target pthread.
+
 config TESTING_LOOP_SCALE
        int "Loop scale of spinlock test (N x 10,000)"
        default 5 if MM_KASAN
diff --git a/testing/ostest/Makefile b/testing/ostest/Makefile
index ba2883025..9574f4774 100644
--- a/testing/ostest/Makefile
+++ b/testing/ostest/Makefile
@@ -99,6 +99,9 @@ endif
 ifneq ($(CONFIG_DISABLE_PTHREAD),y)
 CSRCS += cancel.c cond.c mutex.c timedmutex.c sem.c semtimed.c barrier.c
 CSRCS += timedwait.c pthread_rwlock.c pthread_rwlock_cancel.c schedlock.c
+ifeq ($(CONFIG_TESTING_OSTEST_PTHREAD_SIGQUEUE),y)
+CSRCS += pthread_sigqueue.c
+endif
 
 ifeq ($(CONFIG_SCHED_WAITPID),y)
 CSRCS += pthread_exit.c
diff --git a/testing/ostest/ostest.h b/testing/ostest/ostest.h
index 130dacd72..a23c95eb8 100644
--- a/testing/ostest/ostest.h
+++ b/testing/ostest/ostest.h
@@ -288,6 +288,12 @@ void pthread_exit_test(void);
 
 void pthread_cleanup_test(void);
 
+/* pthread_sigqueue.c *******************************************************/
+
+#ifdef CONFIG_TESTING_OSTEST_PTHREAD_SIGQUEUE
+void pthread_sigqueue_test(void);
+#endif
+
 /* barrier.c ****************************************************************/
 
 void barrier_test(void);
diff --git a/testing/ostest/ostest_main.c b/testing/ostest/ostest_main.c
index a0b42a67f..f84e975ad 100644
--- a/testing/ostest/ostest_main.c
+++ b/testing/ostest/ostest_main.c
@@ -554,6 +554,14 @@ static int user_main(int argc, char *argv[])
       check_test_memory_usage();
 #endif
 
+#ifdef CONFIG_TESTING_OSTEST_PTHREAD_SIGQUEUE
+      /* Verify pthread_sigqueue interface */
+
+      printf("\nuser_main: pthread_sigqueue test\n");
+      pthread_sigqueue_test();
+      check_test_memory_usage();
+#endif
+
       /* Verify pthreads and condition variable timed waits */
 
       printf("\nuser_main: timed wait test\n");
diff --git a/testing/ostest/pthread_sigqueue.c 
b/testing/ostest/pthread_sigqueue.c
new file mode 100644
index 000000000..0b41904c5
--- /dev/null
+++ b/testing/ostest/pthread_sigqueue.c
@@ -0,0 +1,277 @@
+/****************************************************************************
+ * apps/testing/ostest/pthread_sigqueue.c
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.  The
+ * ASF licenses this file to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ *
+ ****************************************************************************/
+
+/****************************************************************************
+ * Included Files
+ ****************************************************************************/
+
+#include <nuttx/config.h>
+
+#include <assert.h>
+#include <errno.h>
+#include <pthread.h>
+#include <semaphore.h>
+#include <signal.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <unistd.h>
+
+#include "ostest.h"
+
+/****************************************************************************
+ * Pre-processor Definitions
+ ****************************************************************************/
+
+#define TEST_SIGNO     SIGUSR1
+#define TEST_VAL_INT   42
+
+/****************************************************************************
+ * Private Data
+ ****************************************************************************/
+
+static sem_t g_ready_sem;
+static sem_t g_done_sem;
+static struct sigaction g_oact;
+static bool g_act_installed;
+static volatile bool g_sigreceived;
+static volatile int g_received_signo;
+static volatile int g_received_code;
+static volatile int g_received_val;
+
+/****************************************************************************
+ * Private Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: sigqueue_handler
+ ****************************************************************************/
+
+static void sigqueue_handler(int signo, FAR siginfo_t *info,
+                             FAR void *ucontext)
+{
+  if (info != NULL)
+    {
+      g_received_signo = signo;
+      g_received_code  = info->si_code;
+      g_received_val   = info->si_value.sival_int;
+      g_sigreceived    = true;
+    }
+
+  sem_post(&g_done_sem);
+}
+
+/****************************************************************************
+ * Name: sigqueue_thread
+ ****************************************************************************/
+
+static FAR void *sigqueue_thread(FAR void *arg)
+{
+  struct sigaction act;
+  sigset_t set;
+  int status;
+
+  /* Setup signal action */
+
+  act.sa_sigaction = sigqueue_handler;
+  act.sa_flags     = SA_SIGINFO;
+  sigemptyset(&act.sa_mask);
+
+  status = sigaction(TEST_SIGNO, &act, &g_oact);
+  if (status != OK)
+    {
+      printf("sigqueue_thread: sigaction failed, errno=%d\n", errno);
+      ASSERT(false);
+      return (FAR void *)ERROR;
+    }
+
+  g_act_installed = true;
+
+  /* Unblock test signal */
+
+  sigemptyset(&set);
+  sigaddset(&set, TEST_SIGNO);
+  status = pthread_sigmask(SIG_UNBLOCK, &set, NULL);
+  if (status != OK)
+    {
+      printf("sigqueue_thread: pthread_sigmask failed: %d\n", status);
+      ASSERT(false);
+      return (FAR void *)ERROR;
+    }
+
+  /* Notify sender that we are ready */
+
+  sem_post(&g_ready_sem);
+
+  /* Wait for signal delivery */
+
+  while (sem_wait(&g_done_sem) < 0)
+    {
+      if (errno != EINTR)
+        {
+          printf("sigqueue_thread: sem_wait failed: %d\n", errno);
+          ASSERT(false);
+          return (FAR void *)ERROR;
+        }
+    }
+
+  return NULL;
+}
+
+/****************************************************************************
+ * Public Functions
+ ****************************************************************************/
+
+/****************************************************************************
+ * Name: pthread_sigqueue_test
+ ****************************************************************************/
+
+void pthread_sigqueue_test(void)
+{
+  pthread_t thread;
+  union sigval val;
+  int status;
+
+  sem_init(&g_ready_sem, 0, 0);
+  sem_init(&g_done_sem, 0, 0);
+
+  g_sigreceived    = false;
+  g_received_signo = -1;
+  g_received_code  = -1;
+  g_received_val   = -1;
+  g_act_installed  = false;
+
+  /* Test 1: Invalid signal number error handling */
+
+  val.sival_int = TEST_VAL_INT;
+  status = pthread_sigqueue(pthread_self(), -1, val);
+  if (status != EINVAL)
+    {
+      printf("pthread_sigqueue_test: signo err: %d\n", status);
+      ASSERT(false);
+    }
+
+  /* Test 2: Invalid thread ID error handling */
+
+  status = pthread_sigqueue((pthread_t)-1, TEST_SIGNO, val);
+  if (status != ESRCH)
+    {
+      printf("pthread_sigqueue_test: thread err: %d\n", status);
+      ASSERT(false);
+    }
+
+  /* Test 3: Normal signal queuing to thread */
+
+  status = pthread_create(&thread, NULL, sigqueue_thread, NULL);
+  if (status != OK)
+    {
+      printf("pthread_sigqueue_test: pthread_create: %d\n", status);
+      ASSERT(false);
+      goto errout;
+    }
+
+  /* Wait until target thread has installed the handler and unblocked */
+
+  while (sem_wait(&g_ready_sem) < 0)
+    {
+      if (errno != EINTR)
+        {
+          printf("pthread_sigqueue_test: sem_wait: %d\n", errno);
+          ASSERT(false);
+          goto errout;
+        }
+    }
+
+  /* Send signal with payload to target thread */
+
+  status = pthread_sigqueue(thread, TEST_SIGNO, val);
+  if (status != OK)
+    {
+      printf("pthread_sigqueue_test: pthread_sigqueue: %d\n", status);
+      ASSERT(false);
+      goto errout;
+    }
+
+  /* Join target thread */
+
+  status = pthread_join(thread, NULL);
+  if (status != OK)
+    {
+      printf("pthread_sigqueue_test: pthread_join: %d\n", status);
+      ASSERT(false);
+      goto errout;
+    }
+
+  /* Restore signal action */
+
+  if (g_act_installed)
+    {
+      status = sigaction(TEST_SIGNO, &g_oact, NULL);
+      if (status != OK)
+        {
+          printf("pthread_sigqueue_test: sigaction restore: %d\n", errno);
+          ASSERT(false);
+        }
+
+      g_act_installed = false;
+    }
+
+  /* Verify received signal properties */
+
+  if (!g_sigreceived)
+    {
+      printf("pthread_sigqueue_test: signal not received\n");
+      ASSERT(false);
+    }
+
+  if (g_received_signo != TEST_SIGNO)
+    {
+      printf("pthread_sigqueue_test: signo mismatch: %d\n",
+             g_received_signo);
+      ASSERT(false);
+    }
+
+  if (g_received_code != SI_QUEUE)
+    {
+      printf("pthread_sigqueue_test: si_code mismatch: %d\n",
+             g_received_code);
+      ASSERT(false);
+    }
+
+  if (g_received_val != TEST_VAL_INT)
+    {
+      printf("pthread_sigqueue_test: val mismatch: %d\n",
+             g_received_val);
+      ASSERT(false);
+    }
+
+  printf("pthread_sigqueue_test: SUCCESS\n");
+
+errout:
+  if (g_act_installed)
+    {
+      sigaction(TEST_SIGNO, &g_oact, NULL);
+      g_act_installed = false;
+    }
+
+  sem_destroy(&g_ready_sem);
+  sem_destroy(&g_done_sem);
+}

Reply via email to